1.什么是静态链表
静态链表(StaticList)就是用一个数组来模拟链表,每个元素是一个"节点",里面有两部分:
data ------ 存放数据
cur ------ 存放"下一个节点"的数组下标(就像 next 指针)
额外规则:
下标 0 专门用来存储"链表头指针"。
下标 1 开始 是"备用链表"(空闲结点池)。
cur == -1 表示"没有下一个结点"(就像指针版的 NULL)。
cur == 0 用来表示备用链表已经空了,不能再分配。
2.静态链表代码与过程详解
main.cpp
cpp
#include"StaticList.h"
void main()
{
StaticList SL;
InitSList(SL);
for (int i = 0; i < 5; ++i)
{
Insert(SL, 'A' + i);
}
ShowSList(SL);
Delete(SL);
ShowSList(SL);
}
StaticList.h
cpp
#ifndef __STATICLIST_H__
#define __STATICLIST_H__
#include<stdio.h>
#define MAX_SIZE 20
#define ElemType char
typedef struct ListNode
{
ElemType data;
int cur;
}ListNode;
typedef ListNode StaticList[MAX_SIZE];
int Malloc_SL(StaticList& space);
void Free_SL(StaticList& sapce, int k);
void InitSList(StaticList& space);
void Insert(StaticList& space, ElemType x);
void Delete(StaticList& space);
void ShowSList(StaticList& space);
#endif //__STATICLIST_H__

StaticList.cpp
InitSList ------ 初始化
cpp
void InitSList(StaticList& space)
{
for (int i = 1; i < MAX_SIZE - 1; ++i)
{
space[i].cur = i + 1; // 让 1→2→3→... 串成一条备用链表
}
space[MAX_SIZE - 1].cur = 0; // 最后一个指向 0,表示备用链表结束
space[0].cur = -1; // 真正的链表是空的
}

举例:假设 MAX_SIZE = 6,初始化后数组状态如下:
下标 | data | cur | 说明 |
---|---|---|---|
0 | ? | -1 | 表示链表为空 |
1 | 2 | 空闲链表第1个结点,指向2 | |
2 | 3 | 空闲链表结点,指向3 | |
3 | 4 | 指向4 | |
4 | 5 | 指向5 | |
5 | 0 | 空闲链表结束 |
此时:
空闲链表 = 1→2→3→4→5→0
真实链表 = 空
Malloc_SL ------ 分配结点
cpp
int Malloc_SL(StaticList& space)
{
int i = space[1].cur; // 拿到备用链表的第一个
if (space[1].cur != 0)
space[1].cur = space[i].cur; // 更新备用链表头
return i; // 返回可用结点下标
}

举例:
当前空闲链表是 1→2→3→4→5→0
调用 Malloc_SL(space):
i = space[1].cur = 2,分配到下标 2。
更新 space[1].cur = space[2].cur = 3。
结果:备用链表变成 1→3→4→5→0,返回下标 2 给用户使用。
Free_SL ------ 释放结点
cpp
void Free_SL(StaticList& space, int k)
{
space[k].cur = space[1].cur; // 新释放的结点指向原备用链表头
space[1].cur = k; // 让它成为新的备用链表头
}
举例:
当前空闲链表是 1→3→4→5→0
释放下标 2:
space[2].cur = space[1].cur = 3
space[1].cur = 2
新备用链表:1→2→3→4→5→0
Insert ------ 插入节点(头插法)
cpp
void Insert(StaticList& space, ElemType x)
{
int i = Malloc_SL(space);
if (i == 0) { printf("申请节点空间失败.\n"); return; }
space[i].data = x;
if (space[0].cur == -1) // 链表为空
{
space[i].cur = -1;
}
else // 链表非空
{
space[i].cur = space[0].cur;
}
space[0].cur = i; // 更新头指针
}

举例:
假设 MAX_SIZE=6,此时空链表:space[0].cur = -1。
插入字符 'A':
分配到结点下标 2(假设)。
space[2].data = 'A',space[2].cur = -1。
更新 space[0].cur = 2。
链表:2→-1,对应内容:A。
再插入 'B':
分配下标 3。
space[3].data = 'B',space[3].cur = 2(指向原来的头)。
更新 space[0].cur = 3。
链表:3→2→-1,对应内容:B → A。
ShowSList ------ 遍历打印
cpp
void ShowSList(StaticList& space)
{
int i = space[0].cur;
while (i != -1)
{
printf("%c-->", space[i].data);
i = space[i].cur;
}
printf("Nul.\n");
}

Delete ------ 删除头节点
cpp
void Delete(StaticList& space)
{
int i = space[0].cur; // 当前头结点
space[0].cur = space[i].cur; // 头指针指向下一个
Free_SL(space, i); // 释放旧的头结点
}

举例:
链表是 3→2→-1(内容:B→A)。
删除:
i = 3
更新 space[0].cur = space[3].cur = 2
释放结点 3 → 回到备用链表
新链表:2→-1(内容:A)。