单链表(线性表的链式存储)

                     单链表                                            头插法

 链表             双链表                     建立链表

                     循环链表                                        尾插法

                     静态链表

单链表节点结构

typedef struct Lnode{

       Elemtype data;             //数据域

       struct Lnode *next;        //指针域(指向下一个节点)

}Lnode,*LinkList;

头指针L:指向链表的第一个节点,若头指针L为NULL则表示该链表为空。

单链表的基本操作:

  1. 头插法建立单链表

头插法思想:建立新节点后,先将新节点的指针域指向头指针指向的节点,再将头指针指向新节点。

LinkList List_HeadInsert(LinkList &L){

       Lnode *s ; int x;

       L = (LinkList*)malloc(sizeof(Lnode));

       L ->next= Null;

       Scanf(“%d”,&x)                          //输入要插入的数值

       While(x!=9999){                         //输入9999退出

          s=(Lnode*)malloc(sizeof(Lnode));     //建立新节点
 
          s->data=x;

          s->next=L->next;

          L->next=s;

         scanf(“%d”,&x);

}

return L;

}

注意:使用头插法生成的链表与读入数据的顺序时相反的。

   2.尾插法

尾插法思想:增加一个尾指针r指向最后一个节点,建立新节点后,将尾指针r所指向的节点的指针域指向新节点,再将尾指针r指向新节点。

LinkList List_Wlnsert(LinkList &L){

       int x;

       L = (LinkList*)malloc(sizeof(Lnode));

       Lnode *s,*r=L;                   //指针s指向新建节点,指针r指向末尾节点

       scanf(“%d”,&x);

       while(x!=9999){

          s=(Lnode*)malloc(sizeof(Lnode));

          s->data=x;                       //理解这三行代码,前后节点的指针

          r->next=s;

          r=s;

          scanf(“%d”,&x);

}

        r->next=NULL;                       //尾指针r置空

        Return L;

}

时间复杂度:O(n)

          

其余基本操作:查找,删除,插入只需要注意目标节点与前后节点之间指针的关系即可理解。

双链表

双链表的指针与单链表的不同,相较于单链表的单指针,双链表的结点有前后两个指针prior和next,指针prior指向的是前一个结点,而指针next指向的是下一个结点。

数据结构定义:

typedef struct Dnode{

       Elemtype data;

       Struct Dnode *prior,*next;    //前驱指针prior和后驱指针next

}Dnode,*DlinkList;

循环链表

循环单链表:与单链表的不同在于,在最后一个节点的指针next指向的并不是NULL而是指向头节点。

循环双链表

由前面的循环单链表与双链表的定义可知循环双链表的定义,唯一需要注意的是头节点的指针prior指向的是尾结点。例:若*p指向的是尾结点,则p->next==L;

当循环链表为空链表时,头节点的prior与next指针都指向L。

静态链表

静态链表是用借用数组来描述线性表的链式存储结构,静态链表中的结点也有data数据域与next指针域,但是next指针域里面指向的是结点的相对位置也就是在数组中的下标。

注:需要预先分配一块内存空间。

例题:

标准答案:

基本设计思想:通过链表的一次遍历,找到倒数第K个结点的位置。定义两个指针变量p和q,两者初始值都指向头节点的下一个结点(链表的第一个结点),当p移动到第K位时,q开始随着p指针同步移动,当p结点移动到最后一个节点时,q所指的即为倒数第k个结点。

详细实现步骤:

  1. count=0,p和q指向链表表头结点的下一个结点。
  2. 若p为空,则转步骤5;
  3. 若count等于k则q指向下一个结点;否则,count=count+1;
  4. q指向下一个结点,转步骤2;
  5. 若count==k,则查找成功,输出该点的数据域的值,并返回1;否则,说明k值超过了线性表的长度,则代表查找失败。
  6. 算法结束。

 

typedef int Elemtype;           
typedef struct Lnode{                   //结点数据结构
       Elemtype data;
       struct Lnode *Link;
}Lnode, *LinkList;


int search_k(LinkList list,int k){
Lnode *p=list->link,*q=list->link;
int count=0;
While(p!=NULL){
   if(count<k) count++;
   else q=q->link;
   p=p->link;
}
if(count<k)
 return 0;
else{
 printf(“%d”,p->data);
 Return 1;
}

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值