文章目录
✨一、静态链表的提出背景
C语言的指针是个好东西,它可以让我们轻松的操纵内存,所以我们可以比较轻松的实现链表这一数据结构,后来的一些面向对象编程的高级语言,由于存在对象引用机制,从某种角度上也间接的实现了指针的某些作用。但对于一些语言,如Basic、Fortran等早期高级编程语言,没有指针功能,那他们是怎么实现链表的呢?
这里就不得不感叹前人的智慧,居然想出了用数组代替指针描述单链表,我们来看看他们是怎么实现的。
✨二、静态链表的原理
🔥2.1 静态链表的数据类型
首先,我们定义一个结构体类型Node作为节点,为了后续方便,我们把元素个数有MAXSIZE个的Node结构体数组这种类型重定义为StaticLinklist。
#define MAXSIZE 1000//定义最大长度
typedef struct {
int data;
int next;//next代表下一成员的下标
}Node,StaticLinklist[MAXSIZE];
🔥2.2 静态链表所在的空间的初始化
我们利用一个初始化函数把这个结构体数组初始化成下图

数组的最后一个元素我们计划作为头结点一样的东西,此时他的next放0表明头结点还没有建立。
数组的0下标元素作为一个提示域,它的next值代表目前第一个还没被申请的节点的下标。
int InitLinklist(StaticLinklist space)
{
if (MAXSIZE - 1 <= 0)
{
return -1;
}
for (int i = 0; i < MAXSIZE - 1; i++)
{
space[i].next = i + 1;
}
space[MAXSIZE - 1].next = 0;
return 0;
}
🔥2.3 创建静态链表——创建头结点并按顺序输入n个元素
接下来要输入元素了,首先我们要创建头结点,也就是让最后一个元素的next值为1(其实不为1也行,不过这样很麻烦),然后顺序输入n个元素,最后把最后一个元素的next值赋成0表示当前链表到达结尾了。
//顺序输入链表的n个元素
int inputlist(StaticLinklist L, int n)
{
if (n >= MAXSIZE - 1)
return -1;
L[MAXSIZE - 1].next = 1;
int i = 1;
for (i = 1; i <= n; i++)
{
printf("请输入链表的第%d个元素\n", i);
scanf("%d", &L[i].data);
}
L[i - 1].next = 0;
L[0].next = i;
return 0;
}
输入完成后我们的链表状态如图:

🔥2.4 在链表的第i个位置插入元素
与在链表中一样,我们要插入元素必须向空间申请一个空闲的节点给我们来用,所以需要一个static_malloc函数,我们向这个函数传入我们的静态链表,它向我们返回一个开辟好的待使用的位置的下标,并且把0位置的next下标更新为下一个空闲的节点的下标。
//为实现像链表一样的插入元素 我们也需要一个malloc函数 传入我们的静态表 返回一个它为我们开辟好的待用的位置的下标
//返回-1表示没有空间了 插入失败
int static_malloc(StaticLinklist space)
{
int i = space[0].next;
if (i != 0 && i!=MAXSIZE-1)
{
space[0].next = space[i].next;
return i;
}
else
{
return -1;
}
}
接下来就是要插入元素了,这里和链表中很像,我们先找到第i-1个元素,让我们申请的节点的next等于它的next,让第i-1个节点的next值等于我们申请的节点的下标,然后让我们申请的这个节点的值输入进去,不过,这里找第i-1个元素的方法和链表中看起来有所不同,其实是相似的,都是从头结点走i-1步,只不过有指针的情况下我们可以用指针直接实现,没有指针的情况下我们要用下标的next值(这个代替了指针功能的东西)来走到第i-1个元素,先从MAXSIZE-1开始走,k=MAXSIZE-1,k=L[k].next—走一步走到第一个节点的位置,k=L[k].next走两步走到第二个节点的位置,走i-1次,走到第i-1个节点。
//插入静态表的第i个元素
int Insertlist(StaticLinklist space, int i, int e)
{
if (i <= 0 || i > MAXSIZE - 1)
return -1;
int k = MAXSIZE - 1;
//要插入第i个元素,首先要走到第i-1个元素的位置
for (int j = 1; j <= i - 1; j++)
{
k = space[k].next;
//循环一次,走到第一个链表第一个元素,两次,走到链表第一个元素
//循环i-1次,走到链表的第i-1个元素
}
int m = static_malloc(space);
//先把i-1号元素(也就是下标为j的元素)的next赋给m的next
space[m].next = space[k].next;
//然后再让i-1的next是m 就连上了链表
space[k].next = m;
space[m].data = e;
return 0;
}
插入操作的时间复杂度是O(N),N是链表当前长度。
🔥2.5 静态链表长度函数与静态链表打印函数
为了查看我们的静态链表的实现情况,我们可以设计一个静态链表打印函数来看我们的链表的状态,为了打印链表,我们需要知道链表的长度(其实也可以不用,有个求链表长度的函数方便一点)。
实现求静态链表长度的函数和打印静态链表的函数是类似的,都是从头结点开始走一直走到next为0的节点为止,利用计数器统计自己走了几步静态链表就是多长。
//链表长度函数
int listlen(StaticLinklist L)
{
int j = L[MAXSIZE-1].next;</

本文详细介绍了如何使用C语言通过数组模拟链表,包括静态链表的原理、数据结构定义、初始化、插入、删除、查找及排序等操作。重点讨论了静态链表的优点和缺点,以及关键函数的实现。
最低0.47元/天 解锁文章
1079

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



