數據結構之鏈表篇(單鏈表,循環鏈表,雙向鏈表)C語言版

1.鏈表

  鏈表是線性表的一種,由一系列節點(結點)組成,每個節點包含一個數據域和一個指向下一個節點的指針域。鏈表結構可以克服數組需要預先知道數據大小的缺點,而且插入和刪除元素很方便,但是失去數組隨機讀取的優點。鏈表有很多種不同類型:單向鏈表,雙向鏈表和循環鏈表。

在鏈表中第一個節點叫頭節點(如果有頭節點)頭節點不存放有效信息,是爲了方便鏈表的刪除和插入操作,第一個有效節點叫首節點,最後一個節點叫尾節點。

2.單鏈表的操作

  鏈表的操作一般有創建鏈表,插入節點,刪除節點,遍歷鏈表。插入節點的方法有頭插法和尾插法,頭插法是在頭部插入,尾插法是在尾部插入。

  下面以一個帶頭節點,採用尾插法的鏈表說明鏈表的各種操作。

  1 #include<stdio.h>
  2 #include<stdlib.h> 
  3 //單鏈表 
  4 
  5 
  6 //節點結構體 
  7 typedef struct node
  8 {
  9     int value;//數據域 
 10     struct node*next;//指針域 
 11 }Node;
 12 
 13 Node*createList();//創建鏈表並且返回頭節點指針 
 14 void deleteNode(Node*head);//刪除節點 
 15 void insertNode(Node*head);//插入節點 
 16 void travelList(Node*head);//遍歷鏈表
 17  
 18 int main()
 19 {
 20     Node*head=createList();
 21     travelList(head);
 22     insertNode(head);
 23     travelList(head);
 24     deleteNode(head);
 25     travelList(head);
 26     return 0;
 27 }
 28 //創建鏈表,返回頭節點指針 
 29 Node*createList()
 30 {    
 31     //採用尾插法 
 32     Node*head;//頭節點 
 33     Node*tail;//尾節點 
 34     Node*temp=NULL;
 35     int i,value,size;
 36     head=(Node*)malloc(sizeof(Node));//頭節點
 37     head->value=0;
 38     head->next=NULL;
 39     tail=head;
 40     printf("輸入節點個數: ");
 41     scanf("%d",&size);
 42     printf("輸入各個節點的值: ");
 43     
 44     for(i=0;i<size;i++)
 45     {
 46         scanf("%d",&value);    
 47         temp=(Node*)malloc(sizeof(Node)); 
 48         temp->value=value;
 49         tail->next=temp;//讓尾節點的指針域指向新創建的節點 
 50         tail=temp;//尾節點改爲新創建的節點 
 51         tail->next=NULL;//讓尾節點的指針域爲空 
 52     }
 53     return head;
 54 }
 55 //遍歷鏈表 
 56 void travelList(Node*head)
 57 {    
 58     while(head->next!=NULL)
 59     {
 60         printf("%d\n",head->next->value);
 61         head=head->next;
 62     }
 63 }
 64 //插入節點 
 65 void insertNode(Node*head)
 66 {
 67     int value;
 68     int position;
 69     int pos=0;
 70     Node*pre=NULL;//用來保存要插入節點的前一個節點 
 71     Node*newNode;
 72     printf("輸入要插入節點的值: ");
 73     scanf("%d",&value);
 74     printf("要插入的位置: ");
 75     scanf("%d",&position);
 76     while(head!=NULL)
 77     {
 78         pos++;
 79         pre=head;
 80         head=head->next;
 81         if(pos==position)
 82         {    
 83             newNode=(Node*)malloc(sizeof(Node));
 84             newNode->value=value;
 85             newNode->next=pre->next;
 86             pre->next=newNode;
 87         }
 88     }
 89 }
 90 //刪除節點 
 91 void deleteNode(Node*head)
 92 {    
 93     int value;
 94     Node*pre=head;
 95     Node*current=head->next;
 96     printf("輸入要刪除節點的值: ");
 97     scanf("%d",&value);
 98     while(current!=NULL)
 99     {    
100         if(current->value==value)
101         {
102             pre->next=current->next;
103             free(current);//釋放空間 
104             break;
105         }
106         pre=current;
107         current=current->next;
108     }
109 } 

 

 3.循環鏈表

  循環鏈表就是讓尾節點的指針域不再是NULL,而是指向頭節點從而形成一個環。循環鏈表與單鏈表的操作沒有多少差別,只是判斷鏈表是否空應該是

  tail->next==head。

4.雙向鏈表

  雙向鏈表的每一個節點都有兩個指針域,一個前驅指針,指向前一個節點,頭節點的前驅指針爲NULL,一個後繼指針,指向後一個節點,尾節點的後繼指針爲NULL。雙向鏈表可以從任一個節點開始訪問到前後節點,不像單鏈表只能向前。代碼如下。

  1 #include<stdio.h>
  2 #include<stdlib.h> 
  3 //雙向鏈表 
  4 typedef struct node
  5 {
  6     int value;//數據域 
  7     struct node* lNext;//前驅指針 
  8     struct node* rNext;//後繼指針 
  9 }Node;
 10 
 11 Node*createList();//創建鏈表並且返回頭節點指針 
 12 void deleteNode(Node*head);//刪除節點 
 13 void insertNode(Node*head);//插入節點 
 14 void travelList(Node*head);//遍歷鏈表
 15 
 16 int main()
 17 {
 18     
 19     Node*head=createList();
 20     travelList(head);
 21     insertNode(head);
 22     travelList(head);
 23     deleteNode(head);
 24     travelList(head);
 25     return 0;
 26 } 
 27 
 28 Node*createList()
 29 {
 30     Node*head,*tail,*temp;
 31     int num,value,i;
 32     head=(Node*)malloc(sizeof(Node));//頭節點
 33     head->value=0;
 34     head->lNext=NULL;
 35     head->rNext=NULL; 
 36     tail=head;
 37     printf("輸入節點個數: ");
 38     scanf("%d",&num); 
 39     printf("輸入各個節點的值: ");
 40     for(i=0;i<num;i++)
 41     {    
 42         scanf("%d",&value);
 43         temp=(Node*)malloc(sizeof(Node));
 44         temp->value=value;
 45         temp->lNext=tail;
 46         tail->rNext=temp;
 47         tail=temp;
 48         tail->rNext=NULL;
 49     }
 50     return head;
 51 }
 52 
 53 
 54 void deleteNode(Node*head)//刪除節點 
 55 {
 56     
 57     int value;
 58     Node*pre;
 59     Node*current=head->rNext; 
 60     printf("輸入要刪除節點的值: ");
 61     scanf("%d",&value);
 62     pre=head;
 63     while(current!=NULL)
 64     {
 65         if(current->value==value)
 66         {
 67             pre->rNext=current->rNext;//上一個節點指向下一個節點 
 68             current->rNext->lNext=pre;//下一個節點的前驅指針指向上一個節點 
 69             free(current);//刪除該節點 
 70         }
 71         pre=current;
 72         current=current->rNext;
 73     }
 74 }
 75 
 76 void insertNode(Node*head)//插入節點 
 77 {
 78     Node*pre,*temp;
 79     int value,pos;
 80     int num=0;
 81     printf("輸入要插入的值: ");
 82     scanf("%d",&value);
 83     printf("輸入要插入的位置: ");
 84     scanf("%d",&pos);
 85     while(head!=NULL)
 86     {
 87         num++;
 88         pre=head;//保存上一個節點 
 89         head=head->rNext;//當前節點 
 90         if(pos==num)
 91         {
 92             temp=(Node*)malloc(sizeof(Node));
 93             temp->value=value;
 94             temp->lNext=pre;
 95             temp->rNext=head;
 96             head->lNext=temp;
 97             pre->rNext=temp;
 98         }
 99     }
100 }
101 
102 void travelList(Node*head)//遍歷鏈表
103 {
104     while(head->rNext!=NULL)
105     {
106         printf("%d\n",head->rNext->value);
107         head=head->rNext;
108     }
109 }

 

 

 

  其實只要弄懂單鏈表,其他也很簡單的,無論鏈表多複雜,本質還是操作指針的指向,想想就會明白了。

  如果鏈表不會,後面的各種各樣的樹結構,就更不用學了。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章