静态链表
转载自
作者:张先生的blog
来源:CSDN
原文:https://blog.csdn.net/rujin_shi/article/details/79468879
版权声明:本文为博主原创文章,转载请附上博文链接!
用数组来代替指针,来描述单链表
将数组元素分成两个数据域,data和cur。data用来存放数据元素,cur存放该元素的后继在数组中的下标(游标)。<游标实现法>
1.基本结构
/*线性表的静态链表存储结构*/
typedef int ElemType;
typedef struct _staticList
{
ElemType data;
int cur; //游标,0表示无效
}StaticList[MAXSIZE];
在静态链表中,我们将数组的第一个和最后一个元素作为特殊元素处理,不存放数据。
此外,将未被使用的数组元素称为备用链表。
而数组的第一个元素,即下标为0的元素的cur就存放备用链表的第一个结点的下标。
而数组的最后一个元素的cur则存放第一个有数值元素的下标,相当于链表的头结点作用。
2.初始化
//初始化
#define MAXSIZE 1000
void initList(StaticList space)
{
for (int i = 0; i < MAXSIZE - 1; i++)
{
space[i].cur = i + 1;
}
space[MAXSIZE - 1].cur = 0;
}
3.静态链表内存分配
静态链表中存放的是数组,不存在动态链表中结点的申请与释放函数malloc()和free()。
为了辨明数组中哪些分量未被使用,解决的办法是将所有未被使用过的及已被删除的分量用游标链成一个备用的链表。每当进行插入时,便可以从备用链表上取得第一个结点作为待插入的新结点。
//获取备用下标
int mallocList(StaticList space)
{
int i = space[0].cur;
if (i)
{
space[0].cur = space[i].cur;//更新首元素游标
}
return i;
}
4.静态链表的元素个数
//计算元素个数
int listLength(StaticList space)
{
int i = space[MAXSIZE - 1].cur;
int j = 0;
while (i)
{
j++;
i = space[i].cur;
}
return j;
}
5.静态链表的插入
实现:在L中第i个元素之前插入新元素e
现在我们需要在‘乙’和‘丁’之间,插入一个新元素‘丙’。怎么实现呢?
我们只需要将‘丙’放入备用链表的第一个空位置,也就是下标为7的位置。
另外将‘乙’的游标改为7,‘丙’的游标改为3。
这样实现了不移动元素,完成了插入的动作。
//插入 静态链表,在第i个下标前插入,插入的元素
void insertList(StaticList space, int i, ElemType e)
{//包括 头插入,尾插入
if (i < 1 || i > listLength(space) + 1)//判断插入的下标是否正确
{
printf("错误\n");
return;
}
int k = MAXSIZE - 1; //最后一个元素的下标
int j = mallocList(space); //获取备用下标
if (j)
{
space[j].data = e;
for (int index = 1; index < i; index++)//在第i个下标前一个位置
{
k = space[k].cur;
}
space[j].cur = space[k].cur;//新插入的元素游标指向第i个下标的位置
space[k].cur = j;
}
}
6.静态链表的删除操作
与内存分配相对应的有内存回收。
即将空闲结点回收到备用链表中。
//释放空间
void freeList(StaticList space, int j)
{
space[j].cur = space[0].cur; //删除的元素游标更新
space[0].cur = j; //更新首元素为要删除的元素的下标
}
具体删除操作:
//删除元素
void removeList(StaticList space, int i)// i = 3
{//包括首尾元素
if (i < 1 || i > listLength(space))//判断插入的下标是否正确
{
printf("错误\n");
return;
}
int k = MAXSIZE - 1;
for (int index = 1; index < i; index++)
{
k = space[k].cur;
}// k = 2
//printf("%d\n", k);
int j = space[k].cur; //j = 3
space[k].cur = space[j].cur; //跳过要删除的链表 第二个元素游标指向第四个元素
freeList(space, i);
}
总结
优点:
- 在插入和删除操作时只需修改游标,不需要移动元素。从而改进了在顺序存储结构中的插入和删除;
- 操作需要移动大量元素的缺点。
缺点:
- 没有解决连续存储分配带来的表长难度以确定的问题;
- 失去了顺序存储结构随机存取的特性。