数据结构:静态链表(C语言描述)

Posted 知道什么是码怪吗?

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构:静态链表(C语言描述)相关的知识,希望对你有一定的参考价值。

这一篇文章我们总结一下静态链表。

上一篇动态链表链接:https://blog.csdn.net/weixin_41746479/article/details/118468058

主要内容:静态链表的创建、申请节点、回收节点、显示节点数据,用数组模拟链表和一些经典题目。(链表的查找、插入、删除、修改操作与动态链表基本一致,这里就不涉及了)

其实我认为静态链表在C/C++语言当中作用不是很大,因为C/C++可以直接对地址进行处理,动态分配内存可以很方便的实现某些功能。对于那些不能直接对地址进行处理的语言,例如:Java,静态链表就可以起到一定的作用,从而达到不动用地址也能实现动态链表的功能。

①结构体及宏定义如何定义:

代码如下,静态链表也可以像动态链表一样,可以设置单向或双向、循环或者不循环。我这里就只写了单向不循环的静态链表。静态链表的方向和循环的设置思路和动态链表基本相同。

#include<stdio.h>
#define MAX 20
#define ElemType int
typedef struct List{//定义结构体	
	ElemType number;
	ElemType next;	//指向下一个节点的游标 
	ElemType previous; //指向前一个节点的游标 
	 
}L,list[MAX];

②静态链表的初始化:

初始化的时候我们单独处理头节点和尾节点,尾节点的next指向0表示没有空间可以分配,头节点的next指向-1表示创建的是一个空的静态链表。虽然我们一开始就给链表分配了内存,但是我们还没有使用。

void InitList(L *list){//初始化静态链表 

	for(int i=1;i<MAX-1;i++)	
	{
		list[i].number=i;
		list[i].next=i+1;
		list[i].previous=i-1; 
	}
	//初始化的时候,没有任何数据就将头节点指向-1表示为空
	//虽然内存已经分配了,但是还没有使用。 
	list[0].number=0;
	list[0].next=-1;
	list[0].previous=-1;
	list[MAX-1].next=0;
	list[MAX-1].previous=MAX-2;
    //头节点的next记录下一个可以被分配的节点
	
}

③申请节点:

这个函数返回的是可以使用的节点的下标。第一次申请节点的时候,我们提供的是一个空链表,这个时候头节点的next指向的是-1,所以我们需要判断该链表目前是否为空,如果为空,将头节点的next等于下标为1的节点的next(下标为1的节点的next就等于2),函数返回1。如果该链表不是空链表,进行判断是否存在可分配的节点,若有则返回可分配节点的下标。若没有,最后始终返回0。

int MallocList(L *list){//申请节点 

	int i=list[0].next;
	
	if(list[0].next==-1){//如果链表为空的情况 
		list[0].next=2;
      //list[0].next=list[1].next;
		return 1;
	}
	if(list[0].next){//不为空的情况 
		list[0].next=list[i].next;
	}
	return i;
}

④回收节点:

我看了很多篇有关静态链表的文章,其中有关回收节点的写法似乎都有一点点的不妥。他们都没有执行下面代码的第一条语句,如果没有这一条语句,回收过后下一次使用的时候,无法确认原本指向被回收节点的节点下标。也就是说,确实是回收了,但是再次使用的时候无法形成链表。因为当某一个节点被回收了之后,指向被回收节点的节点我们无法确认下标,就无法对这个节点的next进行更改,所以这个节点指向的还是被回收了的节点。再次使用被回收的节点的时候可能会出现多个节点的next指向同一个节点的情况。这是不太好的。所以我在结构体当中增加了一个记录前一个节点坐标的值,以此来避免这种情况。

void FreeList(L *list,int A){//回收节点,A表示需要回收的节点的下标
	list[list[A].previous].next=list[A].next; //将要回收的节点的前一个节点的next指向需要                                                                    
                                              //回收的节点的next 
	list[A].next=list[0].next;//将需要回收的节点的next指向下一个准备分配的空节点 
	list[0].next=A;//将原本准备分配出去的空节点替换为需要回收的节点 
}

⑤显示节点数据:

这里显示的是所有的节点的数据,包括未使用的节点。

void ShowList(L *list){//显示节点数据 
	for(int i=0;i<MAX;i++){
		printf("第%d个节点,next=%d,number=%d\\n",i+1,list[i].next,list[i].number);
	}
}

⑥主函数测试:

int main(){
	list sl;//结构体数组 
	InitList(sl);//初始化链表 
	//初始化之后第一次显示 
	ShowList(sl);

	 
	for(int i=100;i<110;i++){
		sl[MallocList(sl)].number=i;
	}
	printf("\\n\\n");
	//申请节点之后第二次显示 
	ShowList(sl);
	

	printf("\\n\\n");
	FreeList(sl, 5);
	sl[MallocList(sl)].number=4444; 
	FreeList(sl, 6);
	sl[MallocList(sl)].number=5555;
	//回收节点之后再申请节点第三次显示 
	ShowList(sl);
}

运行结果:

第三次运行结果我需要说明一下为什么会出现两个next=11,因为下面的next是初始化的时候赋值的,下面的还没有使用,输出出来就出现了两个next=11。

⑦数组模拟链表与题目:

回看前面的所写的静态链表的代码,会发现就是利用了结构体数组来实现链表的功能。用数组模拟链表的思路和结构体数组实现静态链表大致一样,这里我不想写代码了,我们直接看一道题目深刻理解。

题目链接:https://blog.csdn.net/weixin_41746479/article/details/117775795

其中用数组模拟链表的方法可以画图理解,更加清晰明了。

以上是关于数据结构:静态链表(C语言描述)的主要内容,如果未能解决你的问题,请参考以下文章

数据结构:静态链表(C语言描述)

静态链表循环链表双向链表(C代码实现)

静态链表代码

静态链表C语言数据结构

c语言:建立简单的静态链表,它由3个学生数据的结点组成,要求输出各结点的数据

数据结构05——静态链表循环链表双向链表