1,我們研究數據結構的操作,第一要弄懂它的結構體表示(也就是結構體特點)、第二要清楚它的初始化和撤銷過程。對於靜態鏈表首先分析它的特點:一是采用靜態存儲方式,二是沒有指針。靜態鏈表就是不用指針來表示鏈式關系的一種巧妙實現。
2,靜態鏈表的結構體定義
1 #define MAX 100 2 3 typedef struct 4 { 5 int data; //數據域的類型可以是任意的基類型,包括數組 6 int cur; 7 }component, slinklist[MAX]
3,靜態鏈表的初始化示意圖
4,靜態鏈表的操作集合,與單鏈表一致,均在頭文件defs.h中。此頭文件在前面文章中已經寫出。
5,初始化操作的實現
1 #include"defs.h" 2 3 void InitList(slinklist s) 4 { 5 int i; 6 L[MAX-1].cur = 0; //令鏈表頭結點為空 7 8 for (i=0; i<MAX-2; i++) //其余元素構成備用鏈表 9 L[i].cur = i+1; 10 L[MAX-2].cur = 0; //備用鏈表最后一個元素置為空 11 }
6,靜態鏈表撤銷操作的實現,原理就是將鏈表從第一個元素至最后一個元素插入到備用鏈表第一個元素前
1 #include"defs.h" 2 3 void DestroyList(slinklist s) 4 { 5 int i = L[MAX-1].cur; 6 L[MAX-1].cur = 0; //令頭結點指向空 7 8 int k = L[0].cur; 9 L[0].cur = i; //令備用鏈表頭結點指向鏈表第一個結點 10 11 int j; //用j來記錄鏈表最后一個結點的位序 12 while (i) 13 { 14 j = i; 15 i = L[i].cur; //第i個結點的指針域為空,結束循環,j記錄了最后一個結點 16 } 17 L[j].cur = k; //令鏈表最后一個結點指向備用鏈表第一個結點 18 }
7,靜態鏈表清空操作和撤銷操作是一致的。
8,判斷空操作。ListEmpty.c
1 #include"defs.h" 2 3 int ListEmpty(slinklist s) 4 { 5 if (L[MAX-1].cur == 0) 6 return 0; //返回0代表為空 7 else 8 return 1; //非0代表不為空 9 }
9,求鏈表長度操作.
1 #include"defs.h" 2 3 int ListLength(slinklist s) 4 { 5 int i, j=0; 6 i = L[MAX-1].cur; //i指向第一個結點 7 8 while (i) //最后一個結點的指針域為空,結束循環 9 { 10 ++j; 11 i = L[i].cur; 12 } 13 return j; 14 }
10,取元素操作.
1 #include"defs.h" 2 3 int GetElem(slinklist s, int i, int *e) 4 { 5 int j=1, k = L[MAX-1].cur; 6 if (i<1 || i>ListLength(s)) //判斷位置是否合理 7 exit(0); 8 while (k && j<i) //找到第i個位置 9 { 10 ++j; 11 k = L[k].cur; 12 } 13 *e = L[k].data; 14 return 0; 15 }
11,查找元素操作實現.
1 #include"defs.h" 2 3 int LocateElem(slinklist s, int e) 4 { 5 int i = L[MAX-1].cur; 6 int j = 0; 7 while (i) 8 { 9 ++j; //j作為計數器 10 if (L[i].data == e) 11 return j; 12 i = L[i].cur; 13 } 14 return 0; 15 } 16 17 //i僅是表示其元素的數組下標值,並不是位序
12,求前驅操作實現.
1 #include"defs.h" 2 3 int PriorElem(slinklist L, int cur_e, int *pri_e) 4 { 5 int i = L[MAX-1].cur; 6 int j; 7 while (i) 8 { 9 j = L[i].cur; 10 if (j && L[j].data == cur_e) 11 { 12 *pri_e = L[i].data; 13 return 0; 14 } 15 i = j; 16 } 17 return 0; 18 }
13,求后繼操作的實現
1 #include"defs.h" 2 3 int NextElem(slinklist L, int cur_e, int *nex_e) 4 { 5 int i = L[MAX-1].cur; 6 int j; 7 while (i) 8 { 9 j = L[i].cur; 10 if (j && L[i].data == cur_e) 11 { 12 *nex_e = L[j].data; 13 return 0; 14 } 15 i = j; 16 } 17 return 0; 18 }
14,Malloc函數實現
1 //因為沒有指針,沒有動態分配函數,所以要自己實現 2 3 #include"defs.h" 4 5 int Malloc(slinklist L) //釋放備用鏈表第一個結點 6 { 7 int i = L[0].cur; 8 if (i == 0) //備用鏈表為空,無法分配,退出 9 exit(0); 10 L[0].cur = L[i].cur; //備用鏈表頭結點,指向備用鏈表第二個結點 11 return i; 12 }
15,Free函數實現
1 #include"defs.h" 2 3 void Free(slinklist L, int k) //將位置為k的空閑結點釋放 4 { //即插入到備用鏈表第一個結點前 5 L[k].cur = L[0].cur; 6 L[0].cur = k; 7 } 8 9 //Malloc、Free均是對備用鏈表的操作
16,靜態鏈表插入操作實現
1 #include"defs.h" 2 3 int ListInsert(slinklist L, int i, int e) 4 { 5 int k = L[MAX-1].cur; //k指向第一個結點 6 int j = 1, m, s; 7 8 if (i<1 || i>ListLength(L)+1) //判斷位置是否合理 9 exit(0); 10 11 while (k && j<i-1) //找到第i-1個位置 12 { 13 ++j; 14 k = L[k].cur; 15 } 16 m = L[k].cur; //m指向第i個位置 17 18 s = Malloc(L); //分配一個結點s 19 L[s].data = e; 20 L[s].cur = L[m].cur; 21 L[k].cur = s; 22 return 0; 23 }
17,靜態鏈表刪除操作的實現
1 #include"defs.h" 2 3 int ListDelete(slinklist L, int i, int *e) 4 { 5 int k = L[MAX-1].cur; 6 int j = 1, m; 7 if (i<1 || i>ListLength(L)) //判斷位置是否合理 8 exit(0); 9 10 while (k && j<i-1) //找到第i-1個位置 11 { 12 ++j; 13 k = L[k].cur; 14 } 15 m = L[k].cur; //m指向第i個位置 16 *e = L[m].data; 17 L[k].cur = L[m].cur; 18 Free(L, m); //將空閑結點m釋放到備用鏈表中 19 }
18,遍歷靜態鏈表操作實現
1 #include"defs.h" 2 3 void TravelList(slinklist L) 4 { 5 int j = 0; 6 int i = L[MAX-1].cur; 7 8 while (i) 9 { 10 ++j; 11 printf("第%d個結點為:%d\n", j, L[i].data); 12 i = L[i].cur; 13 } 14 }
