定义:用数组描述的链表叫做静态链表,这种描述方法还有起名叫做游标实现法。
基本操作:
Status InitList(StaticLinkList space) :将一维数组space中各分量链成一个备用链表
int Malloc_SLL(StaticLinkList space):若备用空间链表非空,则返回分配的结点下标,否则返回0
void Free_SSL(StaticLinkList space, int k):将下标为K的空闲结点回收到备用链表
int ListLength(StaticLinkList L):返回L中数据元素个数
Status ListInsert(StaticLinkList L, int i, ElemType e):在L中第i个元素之前插入新的数据元素e
Status ListDelete(StaticLinkList L, int i):删除在L中第i个数据元素e
为什么使用备用空间链表?
为了辨明数组中哪些分量未被使用,解决的办法是将所有未被使用过的及已被删除的分量用游标链成一个备用的链表,
每当进行插入时,便可以从备用链表上取得第一个结点作为待插入的新结点
代码如下:(编译软件VS2013)
#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
#define MAXSIZE 1000 //存储空间初始分配量
typedef int Status; //Status是函数的类型,其值是函数结果状态代码,如OK等
typedef char ElemType; //ElemType类型根据实际情况而定,这里假设为char
//线性表的静态链表存储结构
typedef struct
{
ElemType data;//数据元素
int cur;//游标(Cursor),为0时表示无指向
}Component, StaticLinkList[MAXSIZE];
//输出元素C
Status visit(ElemType c)
{
printf("%c", c);
return OK;
}
//将一维数组space中各分量链成一个备用链表,space[0].cur为头指针,"0"表示为空指针
Status InitList(StaticLinkList space)
{
int i;
for (i = 0; i < MAXSIZE - 1; i++)
{
space[i].cur = i + 1;
}
space[MAXSIZE - 1].cur = 0;
return OK;
}
/*为了辨明数组中哪些分量未被使用,解决的办法是将所有未被使用过的及已被删除的分量用游标链成一个备用的链表,
每当进行插入时,便可以从备用链表上取得第一个结点作为待插入的新结点*/
//若备用空间链表非空,则返回分配的结点下标,否则返回0
int Malloc_SLL(StaticLinkList space)
{
int i = space[0].cur;//当前数组第一个元素的cur存的值,就是要返回的第一个备用空闲的下标
if (space[0].cur)
space[0].cur = space[i].cur;//由于要拿出一个分量来使用了,所以我们就得把它的下一个分量用来做备用
return i;
}
//将下标为K的空闲结点回收到备用链表
void Free_SSL(StaticLinkList space, int k)
{
space[k].cur = space[0].cur;//把第一个元素的cur值赋给要删除的分量cur
space[0].cur = k; //要删除的分量下标赋值给第一个元素的cur
}
//初始条件:静态链表L存在。操作结果:返回L中数据元素个数
int ListLength(StaticLinkList L)
{
int j = 0;
int i = L[MAXSIZE - 1].cur;
while (i)
{
i = L[i].cur;
j++;
}
return j;
}
//在L中第i个元素之前插入新的数据元素e
Status ListInsert(StaticLinkList L, int i, ElemType e)
{
int j, k, l;
k = MAXSIZE - 1;//注意k首先是最后一个元素的下标
if (i<1 || i>ListLength(L) + 1)
return ERROR;
j = Malloc_SLL(L); //获得空闲分量的下标
if (j)
{
L[j].data = e; //将数据赋值给此分量的data
for (l = 1; l <= i - 1; l++) //找到第i个元素之前的位置
{
k = L[k].cur;
}
L[j].cur = L[k].cur;//把第i个元素之前的cur赋值给新元素的cur
L[k].cur = j; //把新元素的下标赋值给第i个元素之前元素的cur
return OK;
}
return ERROR;
}
//删除在L中第i个数据元素e
Status ListDelete(StaticLinkList L, int i)
{
int j, k, l;
k = MAXSIZE - 1;
if (i<1 || i>ListLength(L) + 1)
return ERROR;
for (l = 1; l < i - 1; l++)
k = L[k].cur;
j = L[k].cur;
L[k].cur = L[j].cur;
Free_SSL(L, j);
return OK;
}
//输出L链表
Status ListTraverse(StaticLinkList L)
{
int j = 0;
int i = L[MAXSIZE - 1].cur;
while (i)
{
visit(L[i].data);
i = L[i].cur;
j++;
}
return j;
printf("\n");
return OK;
}
int main()
{
StaticLinkList L;
Status i;
i = InitList(L);
char a = 'A';
printf("初始化L表后,L的长度=%d\n", ListLength(L));
for (int j = 0; j < 4; j++)
{
ListInsert(L, 1, a);
a = a++;
}
printf("在L表头依次插入ABCD后,L数据为:");
ListTraverse(L);
printf("\n");
i = ListInsert(L, 2, 'F');
printf("在L表第2个位置插入F后,L数据为:");
ListTraverse(L);
printf("\n");
i = ListDelete(L, 1);
printf("在L表删除第1个元素后,L数据为:");
ListTraverse(L);
printf("\n");
system("pause");
return 0;
}
结果截图:

静态链表的优缺点:
优点:
在插入和删除操作时,只需修改游标,不需要移动元素,从而改进了在顺序存储结构中的插入和删除操作需要移动大量元素的缺点。
缺点:
1.没有解决连续存储分配带来的表长难以确定的问题
2.失去了顺序存储结构随机存取的特性