单链表和双链表 算法与实现

链表是包含一些数据的独立数据结构(也成为节点)的集合,每个节点都是通过指针链接在一起的。通常节点是动态分配的。事实上,链表中的节点可以存在于内存中的各个地方。,所以在物理上是不是相邻并无影响。

链表在数据结构中占有很大的作用,它可以根据使用情况分配内存,避免内存的浪费。它的插入,删除,查找都是根据指针的访问来实现,删除或添加一个节点不会改变其他数据的位置和内容,和数组相比,链表具有很强的灵活性和可操作性,但是在使用和实现的时候稍微麻烦,而且比较抽象。

 

单链表

在单链表中,每个节点都包含指向下一个节点的指针,最后一个节点的指针为NULL,以标志最后一个节点。之所以叫单链表也是因为每个节点只存在一个节点指针而已,所以只能顺序访问下一个节点,俗话就是过了这个村就没这个店了。为了记住单链表的第一个位置,可以定义一个头指针head。

 

 

单链表的节点创建如下

  1. typedef struct Linear_chain_node   
  2.   
  3. {  
  4.   
  5.     int data;  
  6.   
  7.     struct Linear_chain_node *link;  
  8.   
  9. } NODE;  

创建之后,NODE就是节点的数据类型,它是一个包含一个整形数和一个节点指针的封装数据。

 

 

建立单链表的函数算法实现

  1. NODE *Creat_single_chain(int n)  
  2.   
  3. {  
  4.   
  5.     NODE *head , *current,*previous;  
  6.   
  7.     int i;  
  8.   
  9.     previous=(NODE*)malloc(sizeof(NODE));  
  10.   
  11.     previous->data = 0;  
  12.   
  13.     previous->link = NULL;  
  14.   
  15.     head = previous ;  
  16.   
  17.    
  18.   
  19.     for(i=0;i<n;i++)  
  20.   
  21.     {     
  22.   
  23.         current = (NODE*)malloc(sizeof(NODE));  
  24.   
  25.         scanf("%d",current->data);  
  26.   
  27.         current->link = NULL;  
  28.   
  29.         previous->link = current;  
  30.   
  31.         previous = current;  
  32.   
  33.     }     
  34.   
  35.     return head;  
  36.   
  37. }  

建立单链表中,函数是一个指针函数,指针类型是节点,它最终的返回值是头节点。函数里建立了三个节点指针,分别是头节点指针,当前节点指针和前一个节点指针。先建立头指针,数据为0,指针为NULL。通过传递给该函数的参数n来确定节点的个数。在n个循环内一直建立当前节点,当前节点的数据键盘输入,当前节点指针为空。前一节点的指针指向当前节点,最后把当前指针替换为前一个指针进行下一次循环。

 

 

单链表中插入节点算法(在第i个节点之前)

  1. int Insert(NODE *head , int i , int x)  
  2.   
  3. {  
  4.   
  5.     NODE *current , *new ;  
  6.   
  7.     int j;  
  8.   
  9.     if(i<=0)  
  10.   
  11.         retuen 0;  
  12.   
  13.     current = head;  
  14.   
  15.     j = 0;  
  16.   
  17.     while((j<i-1) && current != NULL)  
  18.   
  19.     {  
  20.   
  21.         current = current->link;  
  22.   
  23.         j++;  
  24.   
  25.     }  
  26.   
  27.     if(current = NULL)  
  28.   
  29.         return 0;  
  30.   
  31.     new = (NODE*)malloc(sizeof(NODE));  
  32.   
  33.     new->data = x;  
  34.   
  35.     new->link = current->link;  
  36.   
  37.     current->link = new;  
  38.   
  39.     return 1;  
  40.   
  41. }  

函数中,先遍历节点,直到找到需要添加节点的位置,如果遍历到最后一个节点,函数返回,如果跳出遍历循环,说明是插入位置,申请一个新的节点,数据为x,指针指向当前节点指向的后一个节点,当前节点(实际上已经是旧的节点)指向新节点。

 

单链表中的删除算法

  1. int Delete(NODE *head , int i)  
  2.   
  3. {  
  4.   
  5.     NODE *previous , *current ;  
  6.   
  7.     int j=1;  
  8.   
  9.    
  10.   
  11.     if(i<1)  
  12.   
  13.         return 0;  
  14.   
  15.     previous = head;  
  16.   
  17.     while((j<i) && previous->link != NULL)  
  18.   
  19.     {  
  20.   
  21.         previous = previous->link;  
  22.   
  23.         j++;  
  24.   
  25.     }  
  26.   
  27.     if(previous->link == NULL)  
  28.   
  29.         return 0;  
  30.   
  31.    
  32.   
  33.     current = previous->link;  
  34.   
  35.     previous->link = current->link;  
  36.   
  37.    
  38.   
  39.     free(current);  
  40.   
  41.    
  42.   
  43.     return 1  
  44.   
  45. }  

函数中,先遍历节点,直到找到需要删除节点的位置,将需要删除的节点前一个节点的指针指向其后一个节点,释放内存。

 

 

 

双向链表

顾名思义,双向链表比单链表的多出了一个节点指针,用来指向前一个节点的数据,这样做的好处不言而喻,避免了寻找前面节点时候发生的不方便之举。在数据结构里后面节点称为后继,前面的节点称为前驱。

 

下面用C描述一下双向链表的建立

 

实际上,双向链表仅仅加入的前向指针,前向指针指向的是前一个节点,而前一个指针的后向指针也是指向后一个节点,通过这种方式实现了前后访问。单链表理解了之后,双链表理解起来也很简单,原理是差不多的。

 

双链表的插入算法

  1. int Insert(NODE *head , int x , int y)  
  2. {  
  3.     NODE *current, *new;  
  4.     current = head->flink;  
  5.     while((current != head) && (current->data != y))  
  6.         current=current->flink;  
  7.     if(current == head)  
  8.             return 0;  
  9.   
  10.     new = (NODE*)malloc(sizeof(NODE));  
  11.     new->data = x;  
  12.     new->blink = current;  
  13.     new->flink = current->flink;  
  14.     (current->flink)->blink = new;  
  15.     current->flink->new;  
  16.     return 1;  
  17. }  

 

双链表的删除算法

  1. int Delete(NODE *head,int x)  
  2. {  
  3.     NODE *current;  
  4.     current = head->flink;  
  5.     while((current != head) && (current->data != x))  
  6.             current=current->flink;  
  7.     if(current == head)  
  8.         return 0;  
  9.   
  10.     (current->blink)->flink = current->flink;  
  11.     (current->flink)->vlink = current->blink;  
  12.   
  13.     free(current);  
  14.     return 1;  
  15. }  
  1. typedef struct double_chain_node  
  2. {  
  3.     int data;  
  4.     struct double_chain_node *blink,*flink;  
  5. }NODE;  
  6.   
  7. NODE *Ceate_double_chain(int n)  
  8. {  
  9.     int i;  
  10.     NODE *head , *previous ,*current;  
  11.     previous = (NODE*)malloc(sizeof(NODE));  
  12.     previous->data = 0;  
  13.     previous->blink = previous->flink = NULL;  
  14.     head = previous;  
  15.   
  16.     for(i=0;i<n;i++)  
  17.     {     
  18.         current = (NODE*)malloc(sizeof(NODE));  
  19.         scanf("%d",¤t->data);  
  20.         current->flink = NULL;  
  21.         current->blink = previous;  
  22.         previous->flink = current;  
  23.         previous = current;  
  24.     }     
  25.     return head;  
  26. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值