可能是順序表研究的細致了一點,單鏈表操作一下子就實現了。這里先實現帶頭結點的單鏈表操作。
大概有以下知識點.
1;結點:結點就是單鏈表中研究的數據元素,結點中存儲數據的部分稱為數據域,存儲直接后繼地址的部分稱為指針域。
2;結點示意圖:
3;頭指針:頭指針始終指向鏈表第一個元素,當有頭結點時頭結點就是鏈表第一個元素。頭指針具有標識左右,故頭指針命名為鏈表的名字,這里為linklist。頭指針是一定存在的。
4;頭結點:引入頭結點的目的是,將鏈表首元結點的插入和刪除操作與其他結點的插入和刪除操作統一起來。(即頭指針地址不在發生變化)
5;單鏈表結點結構體表示:
1 struct LNode 2 { 3 int data; //姑且認為其數據為整型 4 struct LNode * next; 5 }; 6 7 typedef struct LNode * linklist
6;單鏈表的操作集合,頭文件 defs.h
1 #ifndef _DEFS_H_ 2 #define _DEFS_H_ 3 4 #include<stdio.h> 5 #include<stdlib.h> 6 #include<malloc.h> 7 8 struct LNode //單鏈表結點的定義 9 { 10 int data; 11 struct LNode * next; 12 } 13 typedef struct LNode * linklist 14 15 //操作集合 16 void InitList(linklist *L); //申請頭結點,頭指針地址改變 17 void DestroyList(linklist *L); //須釋放頭結點,頭指針地址改變 18 void ClearList(linklist L); //保留頭結點,頭指針地址不變 19 void ListEmpty(linklist L); 20 int ListLength(linklist L); 21 int GetElem(linklist L, int i, int *e); 22 int LocateElem(linklist L, int e); 23 int PriorElem(linklist L, int cur_e, int *pri_e); 24 int NextElem(linklist L, int cur_e, int *nex_e); 25 int ListInsert(linklist L, int i, int e); //插入不改變頭指針的值 26 int ListDelete(linklist L, int i, int *e); //刪除操作也不改變頭指針的值 27 void TravelList(linklist L); 28 #endif
7;InitList操作實現

1 #include"defs.h" 2 3 void InitList(linklist *L) //接受頭指針的地址值 4 { 5 *L = (linklist)malloc(sizeof(struct LNode)); //*L表示頭指針 6 7 if (*L == NULL) 8 { 9 printf("分配結點失敗。\n"); 10 exit(-1); 11 } 12 (*L)->next = NULL; //置頭結點的next域為空 13 }
8;DestroyList操作的實現

1 #include"defs.h" 2 3 void DestroyList(linklist *L) //接受的參數為頭指針的地址值 4 { 5 linklist p ; 6 while (*L) 7 { 8 p = (*L)->next; //釋放結點之前先保存結點的下一個地址,防止線索被斷 9 free(*L); 10 *L = p; //將下一個結點,作為釋放結點 11 } 12 }
9;ClearList操作的實現

1 #include"defs.h" 2 3 void ClearList(linklist L) //保留頭結點 4 { 5 linklist p = L->next; //p將頭指針的next值保存起來,p指向首元結點 6 L->next = NULL; 7 8 DestroyList(&p); //調用撤銷函數,釋放后面的結點 9 10 }
10;ListEmpty操作的實現

1 #include"defs.h" 2 3 void ListEmpty(linklist L) 4 { 5 if (L->next == NULL) //判斷頭結點指針域是否為空 6 printf("鏈表為空.\n"); 7 else 8 printf("鏈表不為空.\n"); 9 }
11;ListLength操作實現

1 #include"defs.h" 2 3 int ListLength(linklist L) 4 { 5 int j=0; //作為計數器 6 linklist p = L->next; //p指向首元結點,作為移動指針 7 8 while (p) //從首元結點開始 9 { 10 ++j; 11 p = p->next; 12 } 13 return j; 14 }
12;GetElem操作實現

1 #include"defs.h" 2 3 int GetElem(linklist L, int i, int *e) // 1<= i <=ListLength(L) 4 { 5 int j = 0; //j作為計數器 6 linklist p = L; 7 8 while (p && j<i) //找到第i個結點 9 { 10 ++j; 11 p = p->next; 12 } 13 if (!p || i<1) //取值位置不合理 14 exit(0); 15 16 *e = p->data; 17 return 0; 18 }
13;LocateElem操作實現

1 #include"defs.h" 2 3 int LocateElem(linklist L, int e) 4 { 5 linklist p = L->next; //p作為移動指針,p指向第一個元素 6 int j = 0; //j作為計數器 7 8 while (p) 9 { 10 ++j; 11 if (p->data == e) 12 return j; 13 p = p->next; 14 } 15 return 0; 16 }
14;PriorElem操作實現

1 #include"defs.h" 2 3 int PriorElem(linklist L, int cur_e, int *pri_e) //第一個元素無前驅 4 { 5 linklist p = L->next; //p指向首元結點 6 linklist q; 7 8 while (p) 9 { 10 q = p->next; //q為p的后繼 11 12 if (q && q->data == cur_e) //則p就是q的前驅 13 *pri_e = p->data; 14 p = q; //循環 15 } 16 return 0; 17 }
15;NextElem操作的實現

1 #include"defs.h" 2 3 int NextElem(linklist L, int cur_e, int *nex_e) //最后一個元素無后繼 4 { 5 linklist p = L->next; //p指向首元結點 6 linklist q; 7 8 while (p) 9 { 10 q = p->next; //q為p的后繼 11 12 if (q && p->data == cur_e) //p有后繼,且p的數據域與當前值相等 13 *nex_e = q->data; 14 p = q; //更新p 15 } 16 return 0; 17 }
16;ListInsert操作的實現

1 #include"defs.h" 2 3 int ListInsert(linklist L, int i, int e) //1<= i <= ListLength(L) 4 { 5 int j=0; //j為基數器 6 linklist p = L; //p為移動指針,p指向頭結點 7 linklist q, s; 8 9 while (p && j<i-1) //找到第i-1個結點 10 { 11 ++j; 12 p = p->next; 13 } 14 15 if (!p || i<1) //插入位置不合理 16 return 0; 17 18 q = p->next; //q指向第i個結點 19 20 s = (linklist)malloc(sizeof(struct LNode)); 21 if (!s) //分配失敗 22 exit(-1); 23 24 s->data = e; //置s的數據域為e 25 s->next = q; //插入操作,是指針連起來 26 p->next = s; 27 return 0; 28 }
17;ListDelete操作的實現

1 #include"defs.h" 2 3 int ListDelete(linklist L, int i, int *e) // 1<= i <=ListLength(L) 4 { 5 int j = 0; //j為計數器 6 linklist p = L; 7 linklist q; 8 9 while (p && j<i-1) //找到第i-1個結點 10 { 11 ++j; 12 p = p->next; 13 } 14 15 if (!p || i<1) //刪除位置不合理 16 exit(0); 17 q = p->next; //q指向第i個結點 18 19 *e = q->data; //先將第i個結點的數據域帶出 20 p->next = q->next; //連起指針 21 free(q); //釋放第i個結點 22 23 return 0; 24 }
18;TravelList操作實現

1 #include"defs.h" 2 3 void TravelList(linklist L) 4 { 5 linklist p = L->next; //p指向首元結點 6 int j = 0; //j為計數器 7 8 while (p) 9 { 10 ++j; 11 printf("第%d個結點的數據域的值為:%d\n", j, p->data); 12 p = p->next; //更新p 13 } 14 }
19;makefile的實現,其代碼與順序表的一樣,這里換成另一種寫法
1 object = main.o InitList.o DestroyList.o ClearList.o ListEmpty.o \ 2 ListLength.o GetElem.o LocateElem.o PriorElem.o NextElem.o \ 3 ListInsert.o ListDelete.o TravelList.o 4 5 test : $(object) 6 gcc -g -Wall -o test $(object) 7 8 $(object) : defs.h 9 10 .PHONY : clean 11 clean : 12 rm -f *.o
20;順序表與單鏈表的比較
順序表是用一段地址連續的存儲單元來存放數據元素,適合查找,不適合頻繁插入和刪除(沒一次操作都是O(n));
單鏈表是用不連續的存儲單元,其數據元素之間是用指針來連接,每一次的查找都必須通過頭指針來遍歷,因此其不適合頻繁的查找。但是對於插入和刪除操作,它不需要移動其它元素,算法時間復雜度為O(1),因此特別適合頻繁的插入和刪除操作。