数据结构(二)——单链表 、带头结点的单链表、循环链表 及其实现

一、 链式存储

      以结点的形式存储数据。除了存放一个结点的信息外,还需附设指针。

           

 

    数据在内存中存储是不连续的,每个结点只能也只有它能知道下一个结点的存储位置。

 

 

二、单链表

  单链表是线性表链式存储的一种,其储存不连续。单链表的数据结构中包含两个变量:数据和指向下一结点的指针。一个结点只知道下一个结点的地址。一个单链表必须有一个头指针,指向单链表中的第一个结点。否则链表会在内存中丢失。

三、单链表的操作和实现

1、单链表定义

2、创建一个空链表

3、打印链表

4、查找数据值为x的结点

5、查找索引值为index的结点

6、在i位置插入一个结点

7、在数据y之后插入一个x结点

8、删除i位置的结点

9、删除值为x的结点

 

1、单链表定义

[cpp]  view plain ?
  1. typedef int datatype;  
  2.   
  3. typedef struct link_node{  
  4.     datatype info;  
  5.     struct link_node* next;  
  6. }node;  

 

2、创建一个空链表

[cpp]  view plain ?
  1. #include"linklist.h"  
  2.   
  3. node* init_linklist(){  
  4.     return NULL;  
  5. }  



3、打印链表

[cpp]  view plain ?
  1. #include"linklist.h"  
  2.   
  3. void display_link_list(node *head){  
  4.     if(head == NULL){  
  5.         printf("the list is empty!\n");  
  6.     }else{  
  7.         node *ptr = head;  
  8.         while(ptr){  
  9.             printf("5%d",ptr->info);  
  10.             ptr = ptr->next;  
  11.         }  
  12.     }  
  13. }  


4、查找数据值为x的结点

[cpp]  view plain ?
  1. #include"linklist.h"  
  2.   
  3. node *find_node(node* head,datatype x){  
  4.     node* ptr= head;  
  5.     while(ptr && ptr->info != x)  
  6.         ptr= ptr->next;  
  7.     return ptr;  
  8. }  


5、查找索引值为index的结点

[cpp]  view plain ?
  1. #include"linklist.h"  
  2.   
  3. node* find_index(node* head,int index){  
  4.     node *ptr = head;  
  5.     int pos = 0;  
  6.     if(index<0){  
  7.         printf("Index Error\n");  
  8.         exit(1);  
  9.     }  
  10.     while(ptr && pos != index){  
  11.         ptr=ptr->next;  
  12.         pos++;  
  13.     }  
  14.     return ptr;  
  15. }  


6、在i位置插入一个结点

[cpp]  view plain ?
  1. #include"linklist.h"  
  2.   
  3. node* insert_link_list_index(node *head,int index,datatype x){  
  4.     if(index<0){  
  5.         printf("index error\n");  
  6.         exit(1);  
  7.     }  
  8.     if(index == 0){          //在头插入元素,不用判断链表是否为空  
  9.         node *q = (node*) malloc(sizeof(node));  
  10.         q->info = x;  
  11.         q->next = head;  
  12.         head = q;  
  13.         return head;  
  14.     }  
  15.     else{  
  16.         node *ptr = find_node(head,index-1);  
  17.         node* q = (node*)malloc(sizeof(node));  
  18.         q->info = x;  
  19.         q->next = ptr->next;  
  20.         ptr->next = q;  
  21.         return head;  
  22.     }  
  23. }  


7、在数据y之后插入一个x结点  

[cpp]  view plain ?
  1. #include"linklist.h"  
  2.   
  3. node* intsert_node_yx(node *head,datatype x,datatype y){  
  4.     node *q=find_node(head,y);  
  5.     if(!q){  
  6.         printf("not found the node %d\n");  
  7.         return head;  
  8.     }  
  9.     node *p = (node*)malloc(sizeof(node));  
  10.     p->info = x;  
  11.     p->next= q->next;  
  12.     q->next = p;  
  13.     return head;  
  14. }  

8、删除i位置的结点

[cpp]  view plain ?
  1. #include"linklist.h"  
  2.   
  3. node* del_link_list_index(node* head,int index){  
  4.     if(!head){  
  5.         printf("the list is empty\n");  
  6.         return head;  
  7.     }  
  8.     node* p=head,*q=NULL;  
  9.     if(index == 0){          //第一个元素  
  10.         head = head->next;  
  11.     }else{  
  12.         p=find_index(head,index-1);      //上面定义的第5个函数  
  13.         if(p && p->next){  
  14.             q = p->next;  
  15.             p->next= q->next;  
  16.         }else{  
  17.             printf("the index is not exit\n");  
  18.             return head;  
  19.         }  
  20.     }  
  21.     free(q);  
  22.     return head;  
  23. }  


9、删除值为x的结点

[cpp]  view plain ?
  1. #include"linklist.h"  
  2.   
  3. node* del_link_list_node(node* head,datatype x){  
  4.     if(!head){  
  5.         printf("the list is empty\n");  
  6.         return head;  
  7.     }  
  8.     node* ptr=head,*pre=NULL;  
  9.     while(!ptr && ptr->info != x){  
  10.         pre = ptr;  
  11.         ptr=ptr->next;  
  12.     }  
  13.     if(!ptr){                  //没找到  
  14.         printf("no data\n");  
  15.     }else if(pre){            //第一个就是  
  16.         head=ptr->next;  
  17.     }else{                    //链表中的某个位置  
  18.         pre->next= ptr->next;  
  19.     }  
  20.     free(ptr);  
  21.     return head;  
  22. }  


三、带头结点的单链表

    头结点的单链表中,head指示的是所谓的头结点,它不是实际的结点,不是用来储存数据的。可以这样理解,头结点牺牲了一个储存单元,来化简代码,因为头不可能为空了。或者用来存储一些全局量,比如链表长度,这要依具体需求而定。

     

 

 

四、带头结点的单链表操作实现

因为结构有变化,所以实现有变化但是变化并不多。

1、创建一个空链表

2、打印链表

3、删除值为x的结点

 

1、创建一个空链表

[cpp]  view plain ?
  1. #include"linklist.h"  
  2.   
  3. node* init_hlink_list(){  
  4.     node *head;  
  5.     head=(node*)malloc(sizeof(node));  
  6.     head->next=NULL;  
  7.     return head;  
  8. }  


2、打印链表

[cpp]  view plain ?
  1. #include"linklist.h"  
  2.   
  3. void display_link_list(node *head){  
  4.     if(head->next == NULL){  
  5.         printf("the list is empty!\n");  
  6.     }else{  
  7.         node *ptr = head->next;  
  8.         while(ptr){  
  9.             printf("5%d",ptr->info);  
  10.             ptr = ptr->next;  
  11.         }  
  12.     }  
  13. }  

3、删除值为x的结点

[cpp]  view plain ?
  1. #include"linklist.h"  
  2.   
  3. node* del_link_list_node(node* head,datatype x){  
  4.     if(!head->next){  
  5.         printf("the list is empty\n");  
  6.         return head;  
  7.     }  
  8.     node* ptr=head->next,*pre=head;  
  9.     while(!ptr && ptr->info != x){       
  10.         pre = ptr;  
  11.         ptr=ptr->next;  
  12.     }  
  13.     if(ptr){                
  14.         printf("no data\n");  
  15.     }else {          //两种情况合并到一起了  
  16.         pre->next= ptr->next;  
  17.     }  
  18.     free(ptr);  
  19.     return head;  
  20. }  

五、循环单链表

    链表中最后一个结点的指针指向第一个结点。在这个链表中,若首指针为head,最后一个结点的判断条件为:p->next == head。

 

六、循环单链表的操作和实现

1、打印链表

2、获得最后一个结点

3、找到值为x的结点

4、在i位置插入一个结点

5、在数据y之后插入一个x结点

6、删除值为x的结点

1、打印链表

[cpp]  view plain ?
  1. #include"linklist.h"  
  2.   
  3. void display_link_list(node *head){  
  4.     if(head == NULL){  
  5.         printf("the list is empty!\n");  
  6.     }else{  
  7.         node *ptr = head->next;    
  8.         printf("%5d",head->info);  
  9.         while(ptr != head){    //如果采用ptr->next != head 的方法无法判断最后一个元素!  
  10.             printf("5%d",ptr->info);  
  11.             ptr = ptr->next;  
  12.         }  
  13.     }  
  14. }  


2、获得最后一个结点

[cpp]  view plain ?
  1. #include"linklist.h"  
  2.   
  3. node* get_rear(node *head){  
  4.     node* ptr = head;  
  5.     while(ptr &&ptr->next != head) {  
  6.         ptr= ptr->next;  
  7.     }  
  8.     return head;  
  9. }  


3、找到值为x的结点

[cpp]  view plain ?
  1. #include"linklist.h"  
  2.   
  3. node *find_node_clink(node* head,datatype x){  
  4.     node*ptr = head->next;  
  5.     if(head->info != x){   //如果第一个元素就是就直接走else返回  
  6.         while(ptr != head && ptr->info != x){  
  7.             ptr= ptr->next;  
  8.         }  
  9.         if(ptr == head){   //处理没有找到的情况  
  10.             ptr = NULL;  
  11.         }   
  12.         return ptr;  
  13.     }else{  
  14.         return head;  
  15.     }  
  16. }  

4、在i位置插入一个结点

[cpp]  view plain ?
  1. #include"linklist.h"  
  2.   
  3. node* insert_link_list_index(node *head,int index,datatype x){  
  4.     if(index<0){  
  5.         printf("index error\n");  
  6.         exit(1);  
  7.     }  
  8.     if(index == 0){        //在链表头插入  
  9.         node *p = (node*) malloc(sizeof(node));  
  10.         node *rear;  
  11.         p->info = x;  
  12.         if(!head){        //空链表的处理  
  13.             head = p;  
  14.             p->next = head;  
  15.             return head;  
  16.         }else{            //正常在链表头插入的处理  
  17.             rear = get_rear(head);  
  18.             rear->next = p;  
  19.             p->next = head;  
  20.             head = p  
  21.             return head;  
  22.         }  
  23.     }  
  24.     else{                 //在链表中插入的处理  
  25.         node *ptr= find_node(head,index-1);  
  26.         node* q = (node*)malloc(sizeof(node));  
  27.         q->info = x;  
  28.         q->next = ptr->next;  
  29.         ptr->next = q;  
  30.         return head;  
  31.     }  
  32. }  



5、在数据y之后插入一个x结点

[cpp]  view plain ?
  1. #include"linklist.h"  
  2.   
  3. node* intsert_node_yx(node *head,datatype x,datatype y){  
  4.     node *q=find_node_clink(head,y);         //此处调用的是第3个函数  
  5.     if(!q){  
  6.         printf("not found the node %d\n");  
  7.         return head;  
  8.     }  
  9.     node *p = (node*)malloc(sizeof(node));  
  10.     p->info = x;  
  11.     p->next= q->next;  
  12.     q->next = p;  
  13.     return head;  
  14. }  


6、删除值为x的结点

[cpp]  view plain ?
  1. #include"linklist.h"  
  2.   
  3. node* del_link_list_node(node* head,datatype x){  
  4.     if(!head){  
  5.         printf("the list is empty\n");  
  6.         return head;  
  7.     }  
  8.     node* ptr=head,*pre=NULL;  
  9.     while(ptr->next != head && ptr->info != x){  
  10.         pre = ptr;  
  11.         ptr=ptr->next;  
  12.     }  
  13.     if(ptr->info != x){          //判断最后一个元素的同时也判断了是否找到元素  
  14.         printf("no data\n");  
  15.     }else if(!pre){              //第一个元素就是x  
  16.         pre = get_rear(head);    //不要忘了尾指针指头  
  17.         head=ptr->next;  
  18.         pre->next =ptr;  
  19.     }else{                       //在链表中的情况  
  20.         pre->next= ptr->next;  
  21.     }  
  22.     free(ptr);  
  23.     return head;  
  24. }  
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值