静态链表结构
首先我们先来看看静态链表的结构定义
typedef struct{
ElemType data;
int cur;
}Component,StaticLinkList[MAXSIZE];
如上面代码所示,静态链表需要预先分配容量为MAXSIZE的存储空间(接下来以MAXSIZE值为5进行演示),data定义了数据元素,cur定义了数据元素的游标(可以理解为指向下一节点的指针),用来指示下一数据元素的位置。这种数据结构,虽不能满足动态申请空间,但在线性表的插入和删除元素时,不需要移动元素,只需修改游标就能实现,故仍具有链式存储的主要优点。
静态链表初始化过程如下:
Status InitList(StaticLinkList L)
{
int i;
for(i = 0;i < MAXSIZE-2; i++)
{
L[i].cur = i+1; //除备用链表最后元素,所有结点游标赋值为下一结点的下标
}
L[MAXSIZE-2].cur = 0; //备用链表的表尾
L[MAXSIZE-1].cur = 0; //数据链表表头
return OK;
}
初始化为空的静态链表如下图一所示
图一 空的静态链表
在备用链表中插入数据
接下来才是重点!!!实际上静态链表分为两个链表:备用链表和数据链表(两表的表头位置如上图一所示)。备用链表将未使用空间串联起来,数据链表才是真正存放数据的地方,那么具体是怎样存储数据的呢?接下来我们在数据链表中插入数字1,看以下向数据链表中插入数据的代码:
Status InsertList(StaticLinkList L,int i,ElemType e)
{
if(i<1||i>ListLength(L)+1)
return ERROR;
int j = Malloc_L(L); //备用链表返回空闲数据元素下标以供插入元素
int k = MAXSIZE-1; //数据链表表头的数据元素下标
if(j) //判断备用链表非空
{
L[j].data = e;
for(int s=1;s<=i-1;s++)
k = L[k].cur; //从数据链表头结点遍历到第i-1个元素
L[j].cur = L[k].cur; //将数据插入数据链表的第i-1个元素后
L[k].cur = j; //将第i-1个元素的游标指向刚插入元素的位置
return OK;
}
printf("备用链表为空!\n");
return ERROR; //备用链表为空
}
/*
Malloc_L函数用来返回备用链表表头所指向的第一个空闲空间(此空间将会转换成数据链表空间用来插入数据),此外Malloc_L函数还会修改备用链表表头的游标指向下一空闲空间。函数如下:
*/
int Malloc_L(StaticLinkList L)
{
int i = L[0].cur;
if(L[0].cur) //备用链表非空
{
L[0].cur = L[i].cur; //更新备用链表首结点游标,让其指向下一空白节点
}
return i;
}
调用如下插入函数,其效果如下图二。
InsertList(L,1,1);
图二 向备用链表添加一个元素
图二中用红色字体标注的显然是数据链表了,剩下的黑体字标注的是备用链表,每当要插入一个数据时,备用链表中便有一块空间转化成数据链表的空间,其转换细节分为以下四个步骤:
记录备用链表头L[0]游标,更改L[0]游标为2,使其指向L[2],此时备用链表操作完成
给L[1]的数据元素赋值,L[1]将加入数据链表中
遍历数据链表L[4]到要插入位置(第i位置)的前一个数据元素(第i-1位置),将位于i-1位置的元素游标赋值给位于i位置的元素游标
将插入元素的位置i赋值给位于i-1位置的元素游标,数据链表的插入操作完成
通过以上步骤的分析相信大家都已经熟悉了静态链表的插入操作,那么接下来再执行以下函数,你们能画出静态链表的数据结构图吗?
InsertList(L,1,2);
//综合代码
#include"staticlist.h"
int main()
{
int i = 0, n = 0;
staticlist space;
initstaticlist(space);
printstaticlist(space);
printf("\n");
insertstaticlist(space, 1,1);
insertstaticlist(space, 2, 2);
printstaticlist(space);
printf("\n");
insertstaticlist(space, 3, 6);
printstaticlist(space);//按数组下标输出
printf("\n");
system("pause");
return 0;
}
#include"staticlist.h"
int initstaticlist(staticlist l)
{
int i = 0;
for (i = 0; i < max-1; i++)
{
l[i].next=i+1;
}
//通常数组第一个下标和最后一个下标的数据域不用,这里先把它初始化为0
l[max - max].data = 0;
l[max - 1].data = 0;
l[max - 1].next = 0;
return 1;
}
int lengthstatic(staticlist l)
{
int i = 0, j = 0;
i = l[max - 1].next;//最后一个数组元素(l[9].next)的游标相当于头节点,它指向第一个有数据元素链表的数组下标
while (i)
{
i = l[i].next;//当i为0时,即遍历到了有数据元素的数组的最后一个元素,相当于单链表表尾指针域的NULL
j++;//记录元素个数
}
return j;
}
void printstaticlist(staticlist l)
{
int i = 0;
for (i = 0; i < max; i++)
{
printf("i:%d next:%d data:%d\n", i, l[i].next, l[i].data);
}
}
void printcursor(staticlist l)
{
int i = 0, k = 0;
k = l[max - 1].next;
while (k)
{
printf("%d\n", l[k].data);
k = l[k].next;
}
return;
}
int malloc(staticlist l)
{
int cursor = l[0].next;//返回备用链表当中没有数据元素的第一个数组元素的下标
if (l[0].next)
{
l[0].next = l[cursor].next;
}
return cursor;
}
void insertstaticlist(staticlist l,int i,int value)
{
int k = max - 1;
int j = 0, n = 0;
if (i < 1)
{
return;
}
j = malloc(l);
if (j)
{
l[j].data=value;
for (n = 1; n <= i - 1; n++)
{
k = l[k].next;
}
l[j].next= l[k].next;
l[k].next=j;
}
return ;
}
void free_ssl(staticlist l,int k)//将下标为k的空闲节点回收为备用链表
{
l[k].next = l[0].next;
l[0].next = k;
}
int delstaticlist(staticlist l, int i)
{
int j = 0, k = 0;
k = max - 1;
if (i < 1)
{
return 0;
}
for (j = 1; j <= i - 1; j++)
{
k = l[k].next;
}
j = l[k].next;//这两句的意思是如果有元素被删除了,就更新最后一个数组元素的游标
l[k].next = l[j].next;
free_ssl(l, j);//如果有新的元素插进来,就优先考虑以前删除的空位置
return 1;
}
#ifndef _staticlist_h
#define _staticlist_h
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#define max 10
typedef struct node
{
int data;
int next;
}staticlist[max];
extern int initstaticlist(staticlist l);
extern void printstaticlist(staticlist l);
extern void printcursor(staticlist l);
extern int lengthstatic(staticlist l);
extern int malloc(staticlist l);
extern void insertstaticlist(staticlist l, int i, int value);
extern void free_ssl(staticlist l, int k);
extern int delstaticlist(staticlist l, int i);
#endif
参考:https://blog.csdn.net/zk25257758/article/details/103530626