静态链表的组成有3大要素:
- 数据域 data
- 游标 cursor (是静态链表的关键点)
- 下标 index
按区域可划分为3个部分:
- 数组第一个元素(以下统称此元素为:Start位):非数据区,备用链表中第一个空闲节点的下标;
- 数组最后的元素(以下统称此元素为:End位):非数据区,存放第一个数据元素的下标;
- 静态链表中的数据存放的区域,范围是从第二个元素~倒数第二个元素;
数据存放区划分为2部分:
- 已经存放数据的,即已有数据的数据链,此数据链的第一个元素的下标记录在End位中;
- 还没存放数据的,即备用的链表,备用链表中第一个元素的下标记录在Start位中;
操作上可划分为2部分
- 数据区:包括已经存放数据的区域和End位,用于记录当前静态链中的数据的位置;
- 备用区:包括备用链和Start位,用于记录可存储数据的位置
核心思想:
当前元素就的游标,就是下一个元素的下标;
跟单链表的思想是一样的;
操作流程:
查找数据:在End位中找出第一个数据的下标index -> 由第一个数据游标cursor找到第二个数据的下标index -> 由第二个数据的游标cursor找到第三个数据的下标index -> 以此类推 -> 直至找到游标cursor为0的位置(最后一个元素的cursor为0)
查找备用链:从Start位的cursor中得到第一个空闲位 -> 再在第一个空闲位的cursor得到第二个空闲位 -> 以此类推……
插入数据时,将插入到第一个空闲位中,然后第二个空闲位前移到第一空闲位;
删除数据时,从指定位置中删除,则当前的位置变为第一空闲位,其他的则后移;
另外对于数据区而言:
前一个数据的cursor则需要重新指向下一个数据(即等于当前数据的cursor)
另外,如果删除的是第一个数据,则还需要修改End位的cursor
优点与缺点
优点:
在插入和删除时,只需要修改游标,不需要移动元素,缺点:
没有解决连续存储分配带来的表长难以确定的问题
失去顺序存储结构随机存储的特性
实例
#define MAXSIZE 1000
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int Status;
typedef int ElemType;
typedef struct
{
ElemType data;
int cursor;
} Component, StaticLinkList[MAXSIZE];
// 初始化:将一维数组中的分量链成一备用链表
// 首元素space[MAXSIZE - 1].cursor为头指针,“0”表示空指针
Status InitList(StaticLinkList space)
{
int i;
for (i = 0; i != MAXSIZE - 1; i++)
{
space[i].cursor = i + 1;
}
space[MAXSIZE - 1].cursor = 0; // 目前链表为空,最后一个元素的cursor为0
return OK;
}
// 静态链表的元素的个数
int ListLength(StaticLinkList L)
{
int j = 0;
int i = L[MAXSIZE - 1].cursor;
while(i) // 最后的元素的cursor是0哦
{
i = L[i].cursor;
j++;
}
return j;
}
// 当前
int Malloc_SLL(StaticLinkList space)
{
int i = space[0].cursor; // 当前space[0]中cursor的值,就是第一个空闲的备用链表的下标
if (space[0].cursor)
space[0].cursor = space[i].cursor; // 由于拿出一个分量来使用了,所以我们就得吧它的下一个分量用作备用
return i;
}
Status ListInsert(StaticLinkList L, int i, ElemType e)
{
int j, k, l;
k = MAXSIZE - 1;
if (i < 1 || i > ListLength(L) + 1)
{
return ERROR;
}
j = Malloc_SLL(L); // 获取空闲分量的下标
if (!j)
{
return ERROR;
}
// data的赋值
L[j].data = e; // 将数据赋给此分量的data
// 游标的赋值
for (l = 1; l <= i - 1; l++) // 找到第i个元素之前的位置
{
k = L[k].cursor;
}
L[j].cursor = L[k].cursor; // 把第i个元素之前的cursor赋值给新元素的cursor
L[k].cursor = j; // 把新元素的下标赋值给第i个元素之前元素的cursor
return OK;
}
// 删除
void Free_SSL(StaticLinkList space, int k)
{
// 这样的话,删除的分量就变成了备用链表空闲分量的第一个元素,下次插入的话,就优先它
space[k].cursor = space[0].cursor; // 把第一个元素cursor赋值给要删除的分量cursor
space[0].cursor = k; // 删除分量的cursor的下标赋值第一个元素的cursor
}
Status ListDelete(StaticLinkList L, int i)
{
int j, k;
if (i < 1 || i > ListLength(L))
{
return ERROR;
}
k = MAXSIZE - 1;
for (j = 1; j <= i - 1; j++)
k = L[k].cursor;
j = L[k].cursor;
L[k].cursor = L[j].cursor;
Free_SSL(L, j);
return OK;
}
1万+

被折叠的 条评论
为什么被折叠?



