静态链表你学会了吗

最近在复习大学学习的静态链表数据结构,从代码分析结构,卡在了备用链表那里,通过画图分析才掌握了它的结构。

静态链表结构

首先我们先来看看静态链表的结构定义

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张图片
图一 空的静态链表

在备用链表中插入数据

接下来才是重点!!!实际上静态链表分为两个链表:备用链表和数据链表(两表的表头位置如上图一所示)。备用链表将未使用空间串联起来,数据链表才是真正存放数据的地方,那么具体是怎样存储数据的呢?接下来我们在数据链表中插入数字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);

静态链表你学会了吗_第2张图片
图二 向备用链表添加一个元素

图二中用红色字体标注的显然是数据链表了,剩下的黑体字标注的是备用链表,每当要插入一个数据时,备用链表中便有一块空间转化成数据链表的空间,其转换细节分为以下四个步骤:

  1. 记录备用链表头L[0]游标,更改L[0]游标为2,使其指向L[2],此时备用链表操作完成
  2. 给L[1]的数据元素赋值,L[1]将加入数据链表中
  3. 遍历数据链表L[4]到要插入位置(第i位置)的前一个数据元素(第i-1位置),将位于i-1位置的元素游标赋值给位于i位置的元素游标
  4. 将插入元素的位置i赋值给位于i-1位置的元素游标,数据链表的插入操作完成
    通过以上步骤的分析相信大家都已经熟悉了静态链表的插入操作,那么接下来再执行以下函数,你们能画出静态链表的数据结构图吗?
InsertList(L,1,2);

参考图如下,是不是画对了呢?

静态链表你学会了吗_第3张图片
图三 向备用链表添加一个元素

关于静态链表的基本操作完整代码如下,欢迎大家一起交流学习

#include 
#define MAXSIZE   5
#define ERROR     0
#define OK        1
 
typedef bool Status;
typedef int  ElemType;
 
 
typedef struct{
 
	ElemType data;
	int cur;
 
}Component,StaticLinkList[MAXSIZE];
 
Status visit(ElemType c);									//刷出函数 
 
Status InitList(StaticLinkList L);							//初始化静态链表 
 	
int	Malloc_L(StaticLinkList L); 							//返回备用链表表头所指向的第一个空闲空间供插入元素,更新表头游标指向下一空闲空间
 
Status InsertList(StaticLinkList L,int i,ElemType e);
 
Status DeleteList(StaticLinkList L,int i);
 
void Free_L(StaticLinkList L,int j);
 
int ListLength(StaticLinkList L);
 
void OutList(StaticLinkList L);
 
int main()
{
	StaticLinkList L;
 
	InitList(L);
 
	printf("初始化后长度为:%d\n",ListLength(L));
 
	for(int i=1;i<=2;i++)
	{
		InsertList(L,1,i);
	}
	OutList(L);
	printf("插入两个元素后链表的长度为:%d\n",ListLength(L));
    
	DeleteList(L,2);
	
    OutList(L);
 
    printf("删除一个元素后链表的长度为:%d\n",ListLength(L));
 
	return 0;
}
 
 
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;
}
 
 
//返回备用链表表头所指向的第一个空闲空间供插入元素,更新表头游标指向下一空闲空间
int Malloc_L(StaticLinkList L)
{
	int i = L[0].cur;
 
	if(L[0].cur)   				//备用链表非空
	{
		L[0].cur = L[i].cur; 	//更新备用链表首结点游标 
	}
 
	return i;
}
 
 
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;
 
		return OK;
 
	}
    printf("备用链表为空!\n");
	return ERROR; //备用链表为空
 
}
 
Status DeleteList(StaticLinkList L,int i)
{
 
	if(i<1||i>ListLength(L)+1)
		return ERROR;
 
	int k = MAXSIZE-1;
	int j;
 
	for(int s=1;s<=i-1;s++)
		k = L[k].cur;
 
	j = L[k].cur;
	L[k].cur = L[j].cur;
	Free_L(L,j);
 
	return OK;
 
}
 
void Free_L(StaticLinkList L,int j)
{
	L[j].cur = L[0].cur;
	L[0].cur = j;
}
 
int ListLength(StaticLinkList L)
{
	int j=0;
	int i = L[MAXSIZE-1].cur;
	while(i)
	{
		i = L[i].cur;
		j++;
	}
 
	return j;
}
 
void OutList(StaticLinkList L)
{
	int j = 0;
	int i = L[MAXSIZE-1].cur;		//从数据链表开始遍历
	while(i)
	{
		visit(L[i].data);
		i=L[i].cur;
		j++;
	}
 
	printf("\n");
}
 
Status visit(ElemType c)
{
	printf("%d ",c);
	return OK;
}

你可能感兴趣的:(静态链表,备用链表,数据链表)