静态链表-C语言实现
1.静态链表是在没有指针的编程语言里对链表的一种实现
2.主要是用数组模拟指针
3.在这里,使用结构体使数组的每一个空间可以存储一个数据元素(date)和一个游标(cur),游标的作用相当于链表的指针域,用于记录下一元素的下标是多少
4.在没有结构体(typedef)的语言中,也可以使用两个并行数组实现此功能
此种结构在编程中不一定能用得到,但是这种思想非常巧妙,非常值得我们学习,不多说,直接上代码,亲测可行,有详细注释
#include<stdio.h>
#define MAXSIZE 1000 //静态链表最大空间容量
typedef int ElemType; //数据类型
typedef int Status; //返回值类型
#define OK 1 //操作成功返回值
#define ERROR 0 //操作失败返回值
typedef struct //静态链表的结构体
{
ElemType date; //结点数据
int cur; //结点游标(相当于链表中的地址)
}StaticLinkList[MAXSIZE]; //表名
/*
静态链表的初始化
第一个位置space[0]的cur指向第一个没有数据的位置空间
最后一个位置space[MAXSIZE-1]的cur指向第一个有数据的位置空间,即头结点
*/
Status InitList(StaticLinkList space)
{
for(int i = 0; i < MAXSIZE-1; i++) //为数组中的每个位置的游标赋值
space[i].cur = i + 1;
space[MAXSIZE-1].cur = 0; //使最后一个位置的游标为0
return OK;
}
/*
模拟链表中的malloc函数,在数组中寻找空闲位置空间作为新结点
*/
int malloc_SLL(StaticLinkList space)
{
int i = space[0].cur; //将备用链表的第一个结点位置赋值给i
if(space[0].cur) //如果space[0].cur不是0,即备用链表非空
space[0].cur = space[i].cur; //将备用链表的下一个空闲位置赋值给space[0]
return i;
}
/*获得链表的长度*/
int ListLength(StaticLinkList L)
{
int i, l;
l = 0; //记录链表长度
i = MAXSIZE - 1; //获得头结点下标
i = L[i].cur; //获得头结点位置
while(i) //如果此下标 != 0
{
l++; //长度加1
i = L[i].cur; //下标后移
}
return l; //返回长度l
}
/*
静态链表的插入操作
*/
Status InsertLinkList(StaticLinkList L, int i, ElemType e)
{
int j ,k, l;
k = MAXSIZE-1; //获取头结点的下标
if(i < 1 || i > ListLength(L)+1) //判断要插入的位置是否合理
return ERROR;
j = malloc_SLL(L); //获得备用链表中的第一个位置下标
if(j) //如果此下标不是0,说明还有空间可用
{
L[j].date = e; //将此下标对应位置的数据域赋值为e
for(l = 1; l < i; l++) //遍历链表,寻找i位置之前的结点
k = L[k].cur; //获得此结点的游标
L[j].cur = L[k].cur; //新结点的游标等于i-1位置的游标
L[k].cur = j; //i-1位置的游标等于新结点的游标
return OK; //操作成功
}
return ERROR; //操作失败
}
/*模拟free()函数,将删除的结点空间加入备用空间*/
void free_SSL(StaticLinkList space, int i)
{
space[i].cur = space[0].cur; //删除位置的游标等于0位置的游标
space[0].cur = i; //0位置的游标等于当前结点
}
/*静态链表的删除操作*/
Status DelLinkList(StaticLinkList L, int i)
{
int j, k;
if(i < 1 || i > ListLength(L)+1) //判断删除的位置是否合理
return ERROR;
k = MAXSIZE - 1; //获得头结点的游标
for(j = 1; j < i; j++) //寻找i位置
k = L[k].cur; //游标后移
j = L[k].cur; //将要删除的位置下标赋值给j
L[k].cur = L[j].cur; //使删除结点的前一结点的游标指向删除结点的游标
free_SSL(L, j); //释放删除的结点
return OK;
}
/*静态链表的遍历操作*/
void PrintLinkList(StaticLinkList L)
{
int i;
int j = MAXSIZE - 1; //获得数组最后一个位置的下标
j = L[j].cur; //获得此下标的游标值,即头结点的下标
// printf("长度为%d\n",ListLength(L));
for(i = 1; i <= ListLength(L); i++) //遍历此表
{
printf("第%d个结点的数据是:%d\n", i, L[j].date); //输出每个结点的数据
j = L[j].cur; //获得下一结点的游标
}
}
void main()
{
StaticLinkList L; //创建链表L
int i, e; //i为元素位置,e为元素内容
while(true)
{
printf("请选择对静态链表的操作:\n");
printf("1.初始化\n");
printf("2.插入\n");
printf("3.删除\n");
printf("4.输出\n");
printf("5.退出\n");
int a;
scanf("%d", &a);
switch(a)
{
case 1:
if(InitList(L))
printf("初始化成功\n");
else
printf("初始化失败\n");
break;
case 2:
printf("请输入需要插入的位置:");
scanf("%d", &i);
printf("请输入需要插入的元素:");
scanf("%d", &e);
if(InsertLinkList(L, i, e))
printf("插入成功\n");
else
printf("插入失败\n");
break;
case 3:
printf("请输入需要删除的位置:");
scanf("%d", &i);
if(DelLinkList(L, i))
printf("删除成功\n");
else
printf("删除失败\n");
break;
case 4:
PrintLinkList(L);
break;
case 5:
return;
default:
printf("选择错误\n");
break;
}
}
}