静态链表,一般用于在没有指针等灵活操作内存的高级语言中,如早期的Basic、Fortran等编程语言,静态链表这种存储结构,仍需要预先分配一个较大的空间,但在作为线性表的插入和删除操作时不需移动元素,仅需修改指针,故仍具有链式存储结构的主要优点。
在C语言中,静态链表的表现形式即为结构体数组,结构体变量包括数据域data和游标CUR。
用c语言定义为:
struct{
int cur; //游标
int data; //数据域
};
静态链表记住以下四点即可:
1.对数组的第一个和最后一个元素做特殊的处理,他们的data不存放数据. 2.通常把未使用的数组元素称为备用链表. 3.数组的第一个元素,即下标为0的那个元素的cur存放备用链表的第一个节点的下标. 4.数组的最后一个元素(MAXSIZE-1)则存放第一个有数值的元素的下标,相当于单链表中的头结点作用
当进行静态链表的基本操作如图示:
当静态链表元素为123时:
cur | 1 | 2 | 3 | 0 | 5 | 6 | 7 |
| 1 |
data |
| 1 | 2 | 3 |
|
|
|
|
|
下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | .... | MAXSIZE-1 |
当插入数据4时:
cur | 1 | 2 | 3 | 4 | 0 | 6 | 7 |
| 1 |
data |
| 1 | 2 | 3 | 4 |
|
|
|
|
下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | .... | MAXSIZE-1 |
cur | 3 | 2 | 4 | 5 | 0 | 6 | 7 |
| 1 |
data |
| 1 | 2 | 3 | 4 |
|
|
|
|
下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | .... | MAXSIZE-1 |
c语言实现代码:
StaticLinkList.h
#ifndef _STATIC_LINK_LIST_H_ #define _STATIC_LINK_LIST_H_ #define MAXSIZE 100 typedef enum {ERROR,OK}Status; typedef struct{ int cur; int data; }StaticLinkList[MAXSIZE]; void initStaticLinkList(StaticLinkList staticLinkList); int sll_Malloc(StaticLinkList staticLinkList); void sll_Free(StaticLinkList staticLinkList,int k); void sll_Insert(StaticLinkList staticLinkList,int k,int data); int sll_length(StaticLinkList staticLinkList); void sll_traverse(StaticLinkList staticLinkList,void(*pfun)(int)); void sll_add(StaticLinkList staticLinkList,int data); void sll_del(StaticLinkList staticLinkList,int k); #endif
StaticLinkList.c
#include "StaticLinkList.h" /** * 初始化静态链表 * @param staticLinkList */ /** * 总结: * 1.对数组的第一个和最后一个元素做特殊的处理,他们的data不存放数据. * 2.通常把未使用的数组元素称为备用链表. * 3.数组的第一个元素,即下标为0的那个元素的cur存放备用链表的第一个节点的下标. * 4.数组的最后一个元素(MAXSIZE-1)则存放第一个有数值的元素的下标,相当于单链表中的头结点作用 * @param staticLinkList */ void initStaticLinkList(StaticLinkList staticLinkList) { int i=0; for(;i<MAXSIZE-1;i++) staticLinkList[i].cur = i+1; staticLinkList[MAXSIZE-1].cur = 0; } /** * 分配一个备用节点 * @param staticLinkList * @return */ int sll_Malloc(StaticLinkList staticLinkList) { int k = staticLinkList[0].cur; if(staticLinkList[0].cur) staticLinkList[0].cur = staticLinkList[k].cur; return k; } /** * 添加data到尾部 * @param staticLinkList * @param data */ void sll_add(StaticLinkList staticLinkList,int data) { int k = sll_Malloc(staticLinkList); staticLinkList[k].data = data; staticLinkList[k].cur = 0; int start = staticLinkList[MAXSIZE-1].cur; int pre = MAXSIZE-1; while(start) { pre = start; start = staticLinkList[start].cur; } staticLinkList[pre].cur = k; } /** * * @param staticLinkList * @param k 将下标为k的节点收回到备用链表 */ void sll_Free(StaticLinkList staticLinkList,int k) { staticLinkList[k].cur = staticLinkList[0].cur; staticLinkList[0].cur = k; } /** * 将data插入到链表的第k个位置处 * @param staticLinkList * @param k * @param data */ void sll_Insert(StaticLinkList staticLinkList,int k,int data) { if(k<1 || k>sll_length(staticLinkList)+1)//如果超出范围 return; int start = staticLinkList[MAXSIZE-1].cur; int j = 1; int pre = MAXSIZE-1; while(start && j<k){ pre = start; start = staticLinkList[start].cur; j++; } if(start) { int l = sll_Malloc(staticLinkList); staticLinkList[l].data = data; staticLinkList[l].cur = start; staticLinkList[pre].cur = l; } } int sll_length(StaticLinkList staticLinkList) { int start = staticLinkList[MAXSIZE-1].cur; int j = 1; while(start && j<MAXSIZE-2) { start = staticLinkList[start].cur; j++; } return j; } void sll_traverse(StaticLinkList staticLinkList,void(*pfun)(int)) { int start = staticLinkList[MAXSIZE-1].cur; while(start) { pfun(staticLinkList[start].data); start = staticLinkList[start].cur; } } /** * 删除位置为k的元素 * @param staticLinkList * @param k */ void sll_del(StaticLinkList staticLinkList,int k) { int start = staticLinkList[MAXSIZE-1].cur; int j = 1; int pre = MAXSIZE-1; //上一个元素的游标 while(start && j<k){ pre = start; start = staticLinkList[start].cur; } staticLinkList[pre].cur = staticLinkList[start].cur; sll_Free(staticLinkList,start); }
main2.c
#include "StaticLinkList.h" #include <stdio.h> void pfun(int data); int main(void) { StaticLinkList staticLinkList; initStaticLinkList(staticLinkList); sll_add(staticLinkList,2); sll_add(staticLinkList,3); sll_add(staticLinkList,4); sll_add(staticLinkList,5); sll_add(staticLinkList,7); sll_Insert(staticLinkList,1,10); sll_traverse(staticLinkList,pfun); sll_del(staticLinkList,1); printf("\n"); sll_traverse(staticLinkList,pfun); return 0; } void pfun(int data) { printf("%d ",data); }
运行结果:
总结:
优点:在插入和删除时,只需要修改游标,不需要移动元素,从而改进了在顺序存储结构的插入和删除元素需要移动大量元素的缺点。
缺点:1.没有解决连续存储带来的表长难以确定的问题。
2.失去了顺序存储带来的随机存取的特性