用C語言的指針實現了單向鏈表中的幾項基本操作:新建鏈表,置空鏈表,插入節點(由於在尾部加入新節點尤為常用,故單獨用一個函數實現),刪除節點。為了以上操作更便捷,另分別寫了返回尾節點和某特定節點的函數。
為了統一插入及刪除節點的操作,使其不因節點位置不同而受到影響(主要是插入或刪除頭節點),我在真正的表頭(我稱之為true_head)前加入一空節點作為表頭。
另外,在特定位置插入、刪除節點時必須確保此位置是有效的。想法是:在表頭中儲存鏈表的長度,在特定位置插入、刪除時,將此位置與長度比較大小,如果位置大於長度,則報錯;如果位置小於長度,則執行操作並更新表頭中的長度信息。長度信息的更新:新建時置為1,置空時重置為0,插入成功則加1,刪除成功則減1。
用結構體定義:
1 typedef struct Node{ 2 int i; 3 struct Node *next; 4 }Node;
新建鏈表:這是唯一一個需要返回頭指針的函數。
1 Node *MakeList(void)//創建帶有空表頭節點的列表並返回表頭,其中表頭儲存的是鏈表的長度 2 { 3 Node *head = (Node *)malloc(sizeof(Node)); 4 Node *true_head = (Node *)malloc(sizeof(Node)); 5 printf("Please type in the element of the head node:"); 6 scanf("%d", &true_head->i); 7 head->next = true_head; 8 true_head->next = NULL; 9 head->i = 1; 10 return head; 11 }
置空鏈表:
1 void MakeNull(Node *head) 2 { 3 head->next = NULL; 4 head->i = 0; 5 }
插入節點:
1 void Insert(Node *head, int i)//在特定位置插入節點 2 { 3 if(i > (head->i + 1))//注意:在i或者i+1位置都沒有問題,在i+1位置相當於Append 4 { 5 printf("Insertion failed because i is too big!\n"); 6 } 7 else 8 { 9 Node *temp = (Node *)malloc(sizeof(Node)); 10 printf("Please type in the element of the new node:"); 11 scanf("%d", &temp->i); 12 Node *pre = GetNode(head, i-1); 13 Node *aft = pre->next;//剛開始以為要把在表尾的插入單獨拿出來討論,但后來發現此時aft不就是NULL了嘛♪(´▽` ) 14 temp->next = aft; 15 pre->next = temp; 16 head->i++; 17 }
1 void Append(Node *head)//在鏈表尾部附加節點 2 { 3 Node *temp = (Node *)malloc(sizeof(Node)); 4 printf("Please type in the element of the new node:"); 5 scanf("%d", &temp->i); 6 Node *pre = GetTail(head); 7 pre->next = temp; 8 temp->next = NULL; 9 head->i++; 10 }
刪除節點:
1 void Remove(Node *head, int i)//刪除特定節點 2 { 3 if(i > head->i) 4 { 5 printf("Removal failed because i is too big!\n"); 6 } 7 else 8 { 9 Node *pre = GetNode(head, i-1);//同插入,尾節點也不需要拿出來 10 Node *temp = pre->next; 11 pre->next = temp->next; 12 head->i--; 13 } 14 }
其他的:
1 Node *GetNode(Node *head, int i)//傳入節點位置,並返回此節點 2 { 3 if(i > head->i) 4 { 5 printf("Failed to get node i because i is too big!\n"); 6 return NULL; 7 } 8 else 9 { 10 Node *temp = head; 11 int k; 12 for(k = 0; k < i; k++) 13 { 14 temp = temp->next; 15 } 16 return temp; 17 } 18 } 19 20 Node *GetTail(Node *head)//返回鏈表尾節點,便於在鏈表尾插入新節點 21 { 22 Node *temp = head; 23 while(NULL != temp->next) 24 { 25 temp = temp->next; 26 } 27 return temp; 28 } 29 30 void PrintList(Node *head)//按從表頭到表尾的順序打印鏈表 31 { 32 Node *temp = head->next;//從真表頭開始打印 33 if(NULL == temp) 34 { 35 printf("There is no element in the list!\n"); 36 } 37 else 38 { 39 int k; 40 for(k = 0; k < head->i; k++) 41 { 42 printf("%d\n", temp->i); 43 temp = temp->next; 44 } 45 } 46 }
問題們:
由於指針掌握不好,對於一些操作有些不知所以然;增加一個指針指向尾節點,就可以把GetTail替換掉,但是在進行插入刪除操作時可能會增加額外的工作;希望增加通過元素返回節點位置的操作。