数据结构 -- 静态链表代码实现(总结)
Posted 庸人冲
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构 -- 静态链表代码实现(总结)相关的知识,希望对你有一定的参考价值。
静态链表是利用数组代替指针来描述单链表,数组的每一个元素都由两个数据域组成,data
和cur
。data
用来存放数据,cur
用来存放下一个元素的在数组中的下标,cur
也被称作游标。
此外整个链表也被逻辑划分为两个部分:已使用链表和备用链表,我们对数组的首元素和尾元素进行特殊处理,不存数据。首元素的cur
中存放备用链表第一个元素的下标;而尾元素的cur
中存放已使用链表的第一个元素的下标,当尾元素cur
为0时说明链表为空。
当链表有存储数据时,已使用链表中的最后一个元素的cur
为0。
特点
- 静态链表利用游标来索引到下一个元素,每次删除和添加元素时只需要修改
cur
值,不需要移动元素。改进了顺序存储结构每次添加和删除都需要移动大量元素的缺点。 - 静态链表没有解决连续存储分配带来表长难以确定的问题。失去链式存储结构随机存储的特性。
代码实现
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#define OK 1 // 状态返回值
#define ERROR 0 // 状态返回值
#define FALSE 0 // 状态返回值
#define TRUE // 状态返回值
#define MAXSIZE 1000 // 数组最大容量
typedef int ElemType; // 数据元素类型
typedef int Status; // 函数操作状态返回类型
// 定义静态链表结构
typedef struct StaticList {
ElemType data; // 数据域
int cur; // 游标
}component, StaticList[MAXSIZE];
// 初始化
Status InitList(StaticList SL)
{
int j = 0;
for (j = 0; j < MAXSIZE - 1; j++)
{
SL[j].cur = j + 1; // 初始化,使每个元素的`cur`都存放下一个元素的下标
}
SL[MAXSIZE - 1].cur = 0; // 最后一个元素的`cur`初始化为0
return OK;
}
// 获取表长
int Listlength(const StaticList SL)
{
int k = SL[MAXSIZE - 1].cur; // 从第一个元素开始
int count = 0; // 计数器
while (k) // k 不为0,则说明该元素存在,进入循环
{
count++; // 计数器+1
k = SL[k].cur; // 不断向后移动
}
return count; // 返回count
}
// 打印元素
void print(ElemType e)
{
printf("%d ", e);
}
// 遍历表
void ListTraverse(StaticList SL)
{
int k = SL[MAXSIZE - 1].cur; // 从第一个元素开始遍历
while (k) // 直到k为 0时 结束
{
print(SL[k].data); // 将数据传给print函数进行打印
k = SL[k].cur;
}
printf("\\n");
}
// 备用链表中分配新空间
// 返回新空间的下标
int Malloc_SSL(StaticList SL)
{
int s = SL[0].cur; // 链表首元素的 cur 存放的是备用链表第一个元素的下标,将该下标赋值给 s
if (s) // 如果 s 不为0 说明表未满
{
SL[0].cur = SL[s].cur; // 既然 s 被分配,则让首元素的 cur 存放 s 后面元素的下标。
}
return s;
}
// 释放被删除元素空间
// 该空间会被放入备用链表第一个位置
void Free_SSL(StaticList SL, int q)
{
SL[q].cur = SL[0].cur; // 首元素的cur 赋值给被释放空间的 cur
SL[0].cur = q; // 首元素的cur 存放被释放空间的下标, 此时下标为q的空间是备用链表第一个位置。
}
// 插入元素
// 将指定元素 e 插入到指定位置 i
Status ListInsert(StaticList SL, int i, ElemType e)
{
// 判断 i 的值是否合适
if (i < 1 || i > Listlength(SL) + 1)
{
return ERROR;
}
// 申请新空间
int s = 0;
s = Malloc_SSL(SL);
if (s) // 如果 s 不为0,说明空间分配成功
{
SL[s].data = e; // 将指定元素插入到 SL[s].data 中
int k = MAXSIZE - 1;
int j = 0;
for (j = 1; j < i; j++) // 移动到插入位置 i 之前
{
k = SL[k].cur;
}
SL[s].cur = SL[k].cur; // 新插入元素.cur 存放指定位置 i 元素的下标
SL[k].cur = s; // i 的前驱元素.cur 则存放 s
return OK;
}
return ERROR;
}
// 删除元素
// 删除指定位置上的元素,并用 e 返回该元素的值
Status ListDelete(StaticList SL, int i, ElemType *e)
{
if (i < 1 || i > Listlength(SL))
{
return ERROR;
}
// 找到第i个位置前的元素
int k = MAXSIZE - 1;
int j = 0;
for (j = 1; j < i; j++)
{
k = SL[k].cur;
}
// 使得 i - 1元素 与 i + 1元素建立联系
int q = SL[k].cur; // 保存被删除元素的下标
SL[k].cur = SL[q].cur; // 使得被删除元素之前元素的 cur 保存为之后元素的下标
// 删除 i 位置元素
*e = SL[q].data; // 返回被删除元素的值
Free_SSL(SL, q);
}
// 获取元素
// 通过位置,获取到元素,并使用 e 返回该元素
Status GetElem(StaticList SL, int i, ElemType* e)
{
if (i < 1 || i > Listlength(SL))
{
return ERROR;
}
// 找到第i个元素
int k = SL[MAXSIZE - 1].cur; // 从第一个元素开始遍历
int j = 0;
for (j = 1; j < i; j++)
{
k = SL[k].cur; // 不断向后遍历,直到i之前结束
}
*e = SL[k].data;
return OK;
}
int main()
{
// 创建静态链表
StaticList SL;
// 创建接收状态返回值变量
Status sta;
// 创建接收元素返回值变量
ElemType e;
// 初始化静态链表
sta = InitList(SL);
printf("初始化是否成功?【%d】(1.成功 0.失败)\\n",sta);
// 插入元素
int i = 0;
for (i = 1; i <= 10; i++)
{
ListInsert(SL, i, i);
}
// 遍历表
printf("插入元素后:");
ListTraverse(SL);
printf("表长为:%d\\n", Listlength(SL));
// 删除元素
ListDelete(SL, 5,&e);
printf("删除元素为:%d\\n", e);
printf("删除元素后:");
ListTraverse(SL);
printf("表长为:%d\\n", Listlength(SL));
// 获取元素
GetElem(SL, 5, &e);
printf("获取的元素为:%d\\n", e);
return 0;
}
以上是关于数据结构 -- 静态链表代码实现(总结)的主要内容,如果未能解决你的问题,请参考以下文章