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 ", j, L[i].data); 12 i = L[i].cur; 13 } 14 }