http://blog.csdn.net/abclixu123/article/details/8210109
鏈表也是線性表的一種,與順序表不同的是,它在內存中不是連續存放的。在C語言中,鏈表是通過指針相關實現的。而單鏈表是鏈表的其中一種,關于單鏈表就是其節點中有數據域和只有一個指向下個節點的指針域。創建單鏈表的方法有兩種,分別是頭插法和尾插法。
所謂頭插法,就是按節點的逆序方法逐漸將結點插入到鏈表的頭部。反之尾插法就是按節點的順序逐漸將節點插入到鏈表的尾部。相對來說,頭插法要比尾插法算法簡單,但是最后產生的鏈表是逆序的,即第一個輸入的節點實際是鏈表的最后一個節點。而為了習慣,通常用尾插法來創建鏈表。下面的代碼就是實現了頭插法和尾插法。代碼在Linux下調試通過。
[cpp]?view plaincopy print?
- #include?<stdio.h>??
- #include?<stdlib.h>??
- ??
- typedef?struct?link??
- {??
- ????char?data;??
- ????struct?link?*next;??
- }linklist;??
- ??
- linklist?*CreateList_Front();???//頭插法創建單鏈表??
- linklist?*CreateList_End();?????//尾插法創建單鏈表??
- void?ShowLinklist(linklist?*h);?//輸出顯示鏈表??
- ??
- int?main(void)??
- {??
- ????int?choice;??
- ????linklist?*head;??
- ??
- ????//head?=?(linklist*)malloc(sizeof(linklist));??
- ????while(1)??
- ????{??
- ????????printf("單鏈表的創建\n");??
- ????????printf("1.使用頭插法創建單鏈表\n");??
- ????????printf("2.使用尾插法創建單鏈表\n");??
- ????????printf("3.鏈表輸出顯示\n");??
- ????????printf("4.退出\n");??
- ????????printf("做出選擇:\n");??
- ????????scanf("%d",&choice);??
- ????????switch(choice)??
- ????????{??
- ????????//頭插法??
- ????????case?1:??
- ????????????head?=?CreateList_Front();??
- ????????????break;??
- ????????//尾插法??
- ????????case?2:??
- ????????????head?=?CreateList_End();??
- ????????????break;??
- ????????//輸出鏈表??
- ????????case?3:??
- ????????????ShowLinklist(head);??
- ????????????break;??
- ????????//退出程序??
- ????????case?4:??
- ????????????return?0;??
- ????????????break;??
- ????????default:??
- ????????????break;??
- ????????}??
- ????}??
- ????return?1;??
- }??
- ??
- linklist?*CreateList_Front()??
- {??
- ????linklist?*head,?*p;??
- ????char?ch;??
- ??
- ????head?=?NULL;??
- ????printf("依次輸入字符數據(‘#’表示輸入結束):\n");??
- ????ch?=?getchar();??
- ????while(ch?!=?'#')??
- ????{??
- ????????p?=?(linklist*)malloc(sizeof(linklist));??
- ????????p->data?=?ch;??
- ????????p->next?=?head;??
- ????????head?=?p;??
- ????????ch?=?getchar();?????????????//頭插法算法簡單?核心就兩句p->next?=?head;head?=?p;??
- ????}??
- ????return?head;??
- }??
- ??
- linklist?*CreateList_End()??
- {??
- ????linklist?*head,?*p,?*e;??
- ????char?ch;??
- ??
- ????head?=?NULL;??
- ????e?=?NULL;??
- ????printf("請依次輸入字符數據('#'表示輸入結束):\n");??
- ????ch?=?getchar();??
- ????while(ch?!=?'#')??
- ????{??
- ????????p?=?(linklist*)malloc(sizeof(linklist));??
- ????????p->data?=?ch;??
- ????????if(head?==?NULL)????????//先判斷輸入的是不是第一個節點??
- ????????{??
- ????????????head?=?p;?????????????
- ????????}??
- ????????else??
- ????????{??
- ????????????e->next?=?p;?????//e始終指向輸入的最后一個節點??
- ????????}??
- ????????e?=?p;??
- ????????ch?=?getchar();???????????
- ????}??
- ????if(e?!=?NULL)???????????????//如果鏈表不為空,則最后節點的下一個節點為空??
- ????{??
- ????????e->next?=?NULL;??
- ????}??
- ????return?head;????????????????//尾插法比頭插法復雜一些,程序中要做兩次判斷,分別是判斷第一個節點和最后一個節點的判斷。且消耗多一個指針變量e。??
- }??
- ??
- void?ShowLinklist(linklist?*h)??
- {??
- ????linklist?*p;??
- ??
- ????p?=?h;??
- ????while(p?!=?NULL)??
- ????{??
- ????????printf("%c?",?p->data);??
- ????????p?=?p->next;??
- ????}??
- ????printf("\n");??
- }??
通過上述代碼可以看出,尾插法確實比頭插法復雜點,多了兩個判斷。但是這是可以解決的,通過添加一個頭節點,此節點不存放數據域,只是存放指向下個節點的指針域就是了。這樣就可以免除掉兩次判斷。整體也要清晰點了。下面是增加一個頭節點后尾插法的實現代碼:
[cpp]?view plaincopy print?
- #include?<stdio.h>??
- #include?<stdlib.h>??
- ??
- typedef?struct?list??
- {??
- ????char?data;??
- ????struct?list?*next;??
- }linklist;??
- ??
- linklist?*CreateList_End();?????//尾插法創建鏈表??
- void?ShowLinklist(linklist?*h);?//輸出顯示鏈表??
- ??
- int?main(void)??
- {??
- ????linklist?*head;??
- ??
- ????printf("使用尾插法創建鏈表(改進版)\n");??
- ????printf("請依次輸入字符數據(‘#’表示輸入結束):\n");??
- ????head?=?CreateList_End();????????//創建鏈表??
- ????ShowLinklist(head);?????????????//輸出鏈表??
- }??
- ??
- linklist?*CreateList_End()??
- {??
- ????linklist?*head,?*p,?*e;??
- ????char?ch;??
- ??
- ????head?=?(linklist*)malloc(sizeof(linklist));??
- ????e?=?head;???????????//讓e指向頭節點??
- ????ch?=?getchar();??
- ????while(ch?!=?'#')??
- ????{??
- ????????p?=?(linklist*)malloc(sizeof(linklist));??
- ????????p->data?=?ch;???
- ????????e->next?=?p;?????//把新節點添加到表尾??
- ????????e?=?p;??????????????//把指針指向新節點??
- ????????ch?=?getchar();??
- ????}?????
- ????e->next?=?NULL;??????????//尾節點的指針域置空??
- ????return?head;??
- }??
- ??
- void?ShowLinklist(linklist?*h)??
- {??
- ????linklist?*p;??
- ??
- ????p?=?h->next;??
- ????while(p?!=?NULL)??
- ????{??
- ????????printf("%c?",?p->data);??
- ????????p?=?p->next;??
- ????}??
- ????printf("\n");??
- }??
添加了一個頭節點后代碼是不是就要清晰點了呢?