静态链表介绍
静态链表,也是线性存储结构的一种,它兼顾了顺序表和链表的优点于一身,其如构造线性表的操作需要预先分配一个大的空间,每个节点存储元素值以及游标代替指针指示下一个节点在数组中的相对位置。
其在线性表中进行插入和删除操作时不需要移动元素,仅需修改指针的值,因此其具有链式结构的优点。
例如,使用静态链表存储 {1,2,3} 的过程如下:
(1)创建一个足够大的数组,假设大小为 6,如图 所示:
(2)在将数据存放到数组中时,给各个数据元素配备一个整形变量,此变量用于指明各个元素的直接后继元素所在数组中的位置下标。
静态链表的构造
(1)静态链表的节点构造
typedef struct
{
ElemType data;
int cur;
} Component,StaticLinkList[MAXSIZE];
一个区域(data)用来存放实际数据;
另一个区域(cur)用来存放“指向”的下一个数据区域数组的下标(这里的指向并不指的是指针),cur也被称之为游标,它里面存放的是数组的下标(先不管存放的规则如何,存放的就是数组的下标)
数组中的元素(除了第一个和最后一个)按照有没有被使用分类的,可以分为两类(就像上面的红色和绿色),这两类元素可以分别构成链,我们可以把没有使用的那个链叫做被备用链。
数组中的第一个元素(下标0)与最后一个元素(下标n-1)是不存放数据的,第一个元素的cur存放备用链的第一个元素的下标,最后一个元素的cur存放使用的链表的第一个元素的下标。比如上图中最后一个元素中cur放的是1,1是第一个红色框的下标。
(2)静态链表的实现
在数据链表未初始化之前,数组中所有位置都处于空闲状态,因此都应被链接在备用链表上:
代码如下:
Status InitList(StaticLinkList space) //初始化静态链表
{
for (int i = 0; i < MAXSIZE - 1; i++)
space[i].cur = i + 1;
space[MAXSIZE - 1].cur = 0;
return OK;
}
当向静态链表中添加数据时,需提前从备用链表中摘除节点,以供新数据使用。
备用链表摘除节点最简单的方法是摘除 a[0] 的直接后继节点;同样,向备用链表中添加空闲节点也是添加作为 a[0] 新的直接后继节点。因为 a[0] 是备用链表的第一个节点,我们知道它的位置,操作它的直接后继节点相对容易,无需遍历备用链表,耗费的时间复杂度为 O(1)。
向静态链表中添加元素 1 的过程如图所示:
链表的插入操作不需要想线性表一样进行元素的移位操作,其只需要修改指针指向的位置即可完成插入。
(1)首先找到备用链的第一个元素的下标j,并将其赋值。
(2)假设插入的位置为i,判断i是否属于使用链表的范围内,若属于则从头遍历找到下标为i-1的元素位置。
(3)将j的cur赋值为i-1的cur,然后再将i-1的cur等于j,完成插入工作。实际上就是动态链表的插入操作,原理是一样地。
Status ListInsert(StaticLinkList space, int i, Elemtype e) //插入元素
{
int j,k,l;
k = MAXSIZE - 1;
if (i<1 || i>ListLength(space) + 1)
return ERROR;
j = Malloc_SSL(space);
if (j)
{
space[j].data = e;
for (l = 1; l <= i - 1; l++)
k = space[k].cur;
space[j].cur = space[k].cur;
space[k].cur = j;
return OK;
}
else
return ERROR;
}
静态链表中删除指定元素,只需实现以下 2 步操作:
将存有目标元素的节点从数据链表中摘除;
将摘除节点添加到备用链表,以便下次再用;
Status ListDelete(StaticLinkList space, int i) //删除元素
{
int j, k, l;
k = MAXSIZE - 1;
if (i<1 || i>ListLength(space))
return ERROR;
for (j = 1; j <= i - 1; j++)
k = space[k].cur;
j = space[k].cur;
space[k].cur = space[j].cur;
Free_SSL(space, j);
return OK;
}
完整代码如下:
#include <string.h>
#include <stdio.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 1000
typedef int Status;
typedef char Elemtype;
Status visit(Elemtype c) //访问元素
{
printf("%c", c);
return OK;
}
typedef struct //构建结构体
{
Elemtype data;
int cur;
}Component, StaticLinkList[MAXSIZE];
Status InitList(StaticLinkList space) //初始化静态链表
{
for (int i = 0; i < MAXSIZE - 1; i++)
space[i].cur = i + 1;
space[MAXSIZE - 1].cur = 0;
return OK;
}
int Malloc_SSL(StaticLinkList space) //返回备用链表的第一个元素的地址并将space[0].cur指向该元素
{
int i = space[0].cur;
if (space[0].cur)
space[0].cur = space[i].cur;
return i;
}
void Free_SSL(StaticLinkList space,int k) //将元素放回备用链表中的首位
{
space[k].cur = space[0].cur;
space[0].cur = k;
}
int ListLength(StaticLinkList space) //返回链表的长度
{
int j = 0;
int i = space[MAXSIZE - 1].cur;
while (i)
{
i = space[i].cur;
j++;
}
return j;
}
Status ListInsert(StaticLinkList space, int i, Elemtype e) //插入元素
{
int j,k,l;
k = MAXSIZE - 1;
if (i<1 || i>ListLength(space) + 1)
return ERROR;
j = Malloc_SSL(space);
if (j)
{
space[j].data = e;
for (l = 1; l <= i - 1; l++)
k = space[k].cur;
space[j].cur = space[k].cur;
space[k].cur = j;
return OK;
}
else
return ERROR;
}
Status ListDelete(StaticLinkList space, int i) //删除元素
{
int j, k, l;
k = MAXSIZE - 1;
if (i<1 || i>ListLength(space))
return ERROR;
for (j = 1; j <= i - 1; j++)
k = space[k].cur;
j = space[k].cur;
space[k].cur = space[j].cur;
Free_SSL(space, j);
return OK;
}
Status ListTraverse(StaticLinkList space) //打印元素值
{
int j = 0;
int i = space[MAXSIZE - 1].cur;
while (i)
{
visit(space[i].data);
i = space[i].cur;
j++;
}
return j;
printf("\n");
}
int main(void)
{
StaticLinkList L;
int i = 0;
i = InitList(L);
printf("初始化L后长度为:%d\n", ListLength(L));
i = ListInsert(L, 1, 'F');
i = ListInsert(L, 1, 'E');
i = ListInsert(L, 1, 'D');
i = ListInsert(L, 1, 'B');
i = ListInsert(L, 1, 'A');
printf("插入后静态链表为:\n");
ListTraverse(L);
i = ListInsert(L, 3, 'C');
printf("\n在B与D之间插入c后的静态链表为:\n");
ListTraverse(L);
i = ListDelete(L, 1);
printf("\n在删除A后其为:\n");
ListTraverse(L);
printf("\n");
getchar();
return i;
}
结果如下图所示