静态链表:用数组描述的链表叫做静态链表。
数组元素 = 数据域 + 游标域
描述静态链表的数组除了存储静态链表,还存储了一条备用链表。备用链表是存储未被使用的数组元素。
数组的第一个元素和最后一个元素作为特殊元素处理。第一个元素的cur存放备用链表的第一个结点的下标。最后一个元素的cur存放静态链表的第一个结点的下标。
备用链表和静态链表的最后一个元素的cur均为0。
数组元素的存储结构
#define MAXSIZE 20 /*假设链表的最大长度为20*/
typedef struct
{
ElemType data;
int cur; /*游标为0时表示无指向*/
} Component, StaticLinkList[MAXSIZE];
初始化数组,就是把数组中除了第一个元素和最后一个元素的其他元素串成备用链表
Status InitList(StaticLinkList space)
{
int i;
for (i = 0; i < MAXSIZE - 1; ++i)
space[i].cur = i + 1;
space[MAXSIZE - 1].cur = 0; /*目前静态链表为空,最后一个元素的cur为0*/
return OK;
}
静态链表的插入操作:
1、从备用链表中分配一个新结点,并返回新结点的下标
int Malloc_SLL(StaticLinkList space)
{
int i = space[0].cur; /*当前数组第一个元素的cur存的值,就是要返回的第一个备用空间的下标*/
if (space[0].cur)
space[0].cur = space[i].cur; /*由于要拿出一个分量来使用,所以把它的下一个分量用来作为第一个备用分量*/
return i;
}
2、把新结点插入静态链表中
Status ListInsert(StaticLinkList L, int i, ElemType e)
{
int j, k , l;
if (i < 1 || i > ListLength(L) + 1)
return ERROR;
j = Malloc_SLL(L); /*获得空闲分量的下标*/
k = MAXSIZE - 1; /*k首先是最后一个元素的下标*/
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-1个元素的cur值赋值给新元素的cur*/
L[k].cur = j; /*把新元素的下标赋值为第i-1个元素的cur*/
}
return ERROR;
}
静态链表的删除操作:备用链表的第一个结点前插入新结点;静态链表删除一个结点
void Free_SSL(StaticLinkList space, int k)
{
space[k].cur = space[0].cur; /*把第一个元素cur值赋给删除分量的cur*/
space[0].cur = k; /*把要删除的分量下标赋值给第一个元素的cur*/
}
Status ListDelete(StaticLinkList L, int i)
{
int j, k;
k = MAXSIZE - 1;
if (i < 1 || i > ListLength(L))
return ERROR;
for (j = 1; j <= i - 1; j++)
k = L[k].cur;
j = L[k].cur;
L[k].cur = L[j].cur;
Free_SSL(L, j);
return OK;
}
获取静态链表的元素个数
int ListLength(StaticLinkList L)
{
int j = 0;
int i = L[MAXSIZE - 1].cur;
while (i)
{
++j;
i = L[i].cur;
}
return j;
}
静态链表的优点:在插入和删除操作时,只需要修改游标,不需要移动元素,从而改进来在顺序存储结构中的插入删除操作需要移动大量元素的缺点。
静态链表的缺点:没有解决连续存储分配带来的表长难以确定的问题,失去来顺序结构随机存取的特性