【数据结构与算法(c语言)】线性表--静态链表 5张图彻底搞懂

本文详细介绍了静态链表的概念,如何在C语言中使用数组模拟链表结构,包括初始化、插入、删除操作,以及malloc和free的关联。作者还展示了如何通过数组空间管理内存并实现链表遍历和节点访问。
摘要由CSDN通过智能技术生成

1 . 概念

静态链表: 用数组描述的链表叫做静态链表。
静态链表的结构体:

typedef struct
{
        ElemType  data ;                /* 数据, */
        int Cur;                        /*指向下一个节点的y游标cursor,相当于单链表的next指针 */
} Component,  StaticLinkListArray[[MAXSIZE] ; 

如上代码 中数组 StaticLinkList[MAXSIZE] 可以实现链表 ,
先定义一个静态链表数组 staticLink

 StaticLinkListArray space  //使用StaticLinkList定义一个变量 space,这个变量就是一个

数组 stackL 的所有元素 组建成两个链表:有数链表和备用链表。

静态链表: 数组 space中, 正在被使用的数组元素组成。space[MAXSIZE-1].cur(数组最后一个元素的游标) 就是有数链表第一个结点的下标。

备用空闲链表: 数组 space中, 未被使用的数组元素组成。 space[0].cur (数组第一个元素的游标)就是备用链表第一个结点的下标。

数组listArr的第一个元素space[0]不存储数据,作为备用链表的头结点。
数组listArr的第二个元素space[MAXSIZE-1] 也不存储数据,作为有数链表的头结点

2. tip问题

静态表产生原因: 有的语言没有指针,想要实现链表,可以使用数组代替指针。

为什么要学习静态链表 : 对我们理解操作系统的内存非常有帮助,操作系统的内存就相当于是一个数组空间,这个数组空间可以被多个链表同步操作。 C语言中的malloc函数的内部实现,其实就是对空闲链表的操作,以后会写一遍关于malloc()和free()的内部实现

被称为静态的原因: 数组的地址是定义时就确定了,是常量,不在变化,所以此链表叫做静态链表。

3. 图解

静态链表的实现 就是 两个链表使用 同一个数组空间,实现删除、插入、查找等操作 

3.1 定义数组变量 space

定义一个StaticLinkListArray类型的 数组变量 space,作为链表的空间, space数组的元素结构体,结构体内包含data、cur两个变量 。cur指向下一个元素,data用于存放数据。本例中使用静态链表存放12生肖,所以只需要数组元素只需要14个,12个用于存储12生肖,还有两个分别作为空闲链表和 存储数据用的静态链表的头结点
在这里插入图片描述

3.2 初始化数组 space

初始化数组 space ,并形成两个链表:一个备用空闲链表  和一个存放数据的静态链表。
备用空闲链表:  下标为0的元素为头结点的链表,此时空闲链表含有12个空闲结点和一个头结点
静态链表:            下标为 13的元素 为头结点的空链表

在这里插入图片描述

3.3 在静态表中插入元素

在静态表中插入两个元素 “鼠”、“牛”
备用空闲链表: 下标为1和2的元素就变成了存储数据的静态链表的结点
静态链表: 多了两个结点,的头结点的 变成了1

在这里插入图片描述

3.4 在静态表中插入剩下的10个生肖

在这里插入图片描述

3.5 从链表中删除蛇元素

数据为“蛇”的 元素存放在下标为6的结点,那么就将此结点再释放到空闲链表中。
在这里插入图片描述

4. 代码实现

4.1 InitList 初始化列表

原型:Status InitList(StaticLinkListArray space)
功能: 初始化列表,本质上是将数组分为两个链表,将各个元素的cur设置初始值

/*初始化数组,默认各个元素都属于备用链表,  */
Status InitList(StaticLinkListArray space){
	int i;
	for(i=0; i<MAXSIZE-2; i++)
	{
		space[i].cur=i+1; //第一次循环,先将space[0]的游标cur 设置为  数组第二个元素(备用表第一个结点) 的下标
				  //此后的循环,依次将游标设置下一个元素的下标
		
	}
	
       space[MAXSIZE-2].cur = space[MAXSIZE-1].cur=0;  //数组最后一个元素做为有数链表的头结点,空链表,所以游标cur=0;
						  //倒数第二个元素,做为空闲链表的最后一个元素也没有下一个结点,所以游标也设置为0
	
}

4.2 Malloc_SSL 静态链表的申请空间

原型: int Malloc_SSL(StaticLinkListArray space)
功能: 从空闲链表中申请一个结点,本质上就是从空闲立案表中删除一个结点。一般在插入静态链表结点的时候需要调用此方法

/*    在备用链表中查找空闲结点,找到返回空闲结点下标,返回0,说明没有空间了 */
int  Malloc_SSL(StaticLinkListArray space){

		int cursor=space[0].cur;
		space[0].cur=space[cursor].cur;
		return cursor;

	}

4.3 Free_SSL 静态链表的释放空间

原型: void Free_SSL(StaticLinkListArray space,int i)
功能: 将第i个元素释放,还给空闲链表,即将这个元素的结点插入到空闲链表中

/* 释放空间,即在空闲链表中插入下标为i的元素 */
void Free_SSL(StaticLinkListArray space,int i){
	space[i].cur=space[0].cur;
	space[0].cur=i;
}

4.4 ListLength 获取静态链表的长度

原型: int ListLength(StaticLinkListArray space)
功能: 获取静态链表的长度

int ListLength(StaticLinkListArray space)
{
	int count =0; 	     // 统计数量
	int index=MAXSIZE-1 ;// 下标变量初始值 设置为 数链表的头结点下标,

	while(space[index].cur>0)
	{
		++count;
		++index;
	}
	return count;
}

4.5 ListInsert 插入结点

原型: ListInsert(StaticLinkListArray space, int i, ElemType elem)
功能: 在第i个位置插入数据为elem的元素

Status ListInsert(StaticLinkListArray space, int i, ElemType elem)
{
	int newIndex=0,k=0;      //newIndex,从空闲链表中申请元素的下标;k ,当前第几个元素; index,	循环中,当前元素的下标
	int index=MAXSIZE-1;     // index,循环中,当前元素的下标。初始值为 静态链表的头结点下标

	if( ListLength(space) == MAXSIZE-2 ||i<1) //静态表的存储空间已经满了 或者位置小于,返回0
		return ERROR;

	
	if((newIndex = Malloc_SSL(space))>0 ) // 从空闲链表中申请一个空闲元素下标,并赋值给newIndex
	{				    
		space[newIndex].data=elem;
		while(++k<i && space[index].cur>0) 	 // 退出循环的两种可能:
			index=space[index].cur;	  	 // 1. 当k=i时,说明找到第i个位置了
					          	 // 2. space[index].cur=0,说明index 是 存数链表的最后一个元素,
							 //    这种情况说明插入位置i大于链表的长度,那么就把元素直接插入到链表最后的位置
		space[newIndex].cur=space[index].cur;	 
		space[index].cur=newIndex;
		return OK;
	}
	return ERROR;
}

4.6 ListDelete 删除一个结点

原型: Status ListDelete(StaticLinkListArray space, int i)
功能: 从静态链表中删除第i位置的元素

/*从静态链表中删除第i位置的元素 */
Status ListDelete(StaticLinkListArray space, int i)
{
	int k=1,indexDeleted ;// k用于位置的循环; indexDeleted,被删除元素的下标
	int index=MAXSIZE-1;
	if(i<1||i>ListLength(space))  //大于静态链表的长度
		 return ERROR;
	for(k=1; k<i; ++k){
		index=space[index].cur;
	}
	indexDeleted=space[index].cur; //获取被删除元素的下标
	space[index].cur=space[indexDeleted].cur;
	Free_SSL(space, index);
	return OK;

}

4.7 Visit 访问结点元素

原型: Status Visit(ElemType elem)
功能: 访问结点元素,在此函数中为打印元素。主要是给ListTraverse函数当行参使用

Status Visit(ElemType elem) /*对elem操作*/
{
	printf("\t%s",elem);
}

4.8 ListTraverse 遍历静态表

原型: Status ListTraverse(StaticLinkListArray list, Status (*visit)(ElemType))
功能: 遍历静态表,对每个元素调用visit()函数,这里第二个参数使用函数指针,这样遍历函数中可以任意切换访问的方式

/*遍历静态表,对每个元素调用visit()函数 */
Status ListTraverse(StaticLinkListArray list, Status (*visit)(ElemType)){
	int index=MAXSIZE-1;
	int nextIndex;
	while((nextIndex=list[index].cur)>0){
		visit( list[nextIndex].data);
		index=nextIndex;
	}
	printf("\n");
	return OK;
}

单击 完整源码下载

  • 23
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值