【数据结构(二)】线性表(四)链式存储结构之其他链表

静态链表

  • 定义:用数组描述的链表叫做静态链表。
  • 实现:使每个数据元素由两个数据域组成,一个相当于单链表中的数据域,用来存放数据元素,另一个相当于单链表中的指针域,用来存放元素后继在数组中的下标(游标)。
静态链表存储结构
#define MAXSIZE 1000
typedef struct
{
	ElemType data;		//数据域
	int cur;		//游标,为0时无指向
}Component,StaticLinkList[MAXSIZE];
  • 备用链表:数组中未被使用的数组元素称为备用链表。
  • 准备:对数组的第一个元素和最后一个元素做特殊处理。使下标为0的元素的cur存放备用链表的第一个结点的下标,最后一个元素的cur存放第一个有数值的元素下标(即单链表中的头结点),链表为空时为0。
  • 初始化:
int InitList(StaticLinkList space)
{
	for(int i = 0; i < MAXSIZE-1; i++)
		space[i].cur = i+1;		//遍历“指针”
	space[MAXSIZE].cur = 0;		//静态链表为空,最后一个元素的cur为0
	return 1;
}
静态链表的插入
  • 准备:数组链表不能像动态链表直接借用c语言的malloc()和free()函数。实现一个新的函数,使数组第一个元素的cur指向备用链表的下一个(此时的第二个)结点的下标。

  • Malloc_SLL()函数:

int Malloc_SLL(StaticLinkList space)
{
	int i = space[0].cur;		//返回备用链表的第一个结点下标
	if(space[0].cur)		//存在空闲结点
		space[0].cur = space[i].cur;		//下标改为空闲结点所指向的结点下标
	return i;
}
  • 插入ListInsert:思路同单链表,指针域变为结点下标。
int ListInsert(StaticLinkList L, int i, ElemType e)
{
	int j;
	int k = MAX_SIZE - 1;		//声明k,初始化为最后一个元素的下标
	if (i < 1 || i > ListLength(L) + 1)
		return 0;
	j = Malloc_SSL(L);		//获取可插入的空闲结点的下标
	if ( j )
	{
		L[j].data = e;		//赋值给数据域
		for(int l = 1; l <= i - 1; l++)		//找到第i个元素之前的位置
			k = L[k].cur;
		L[j].cur = L[k].cur;		
		L[k].cur = j;		//cur下标的调换
		return 1;
	}
	return 0;
}
静态链表的删除
  • 准备: 实现一个函数,将要删除的结点回收到备用链表。
  • Free_SSL()函数:
void Free_SSL(StaticLinkList space, int k)
{
	space[k].cur = space[0].cur;		//把第一个元素的cur赋值给要删除的结点
	space[0].cur = k;		//把k的下标赋值给第一个元素的cur
}
  • 删除ListDelete:
int ListDelete(StaticLinkList L, int i)
{
	int k;
	int j;
	if (i < 1 || i > ListLength(L))
		return 0;
	k=MAX_SIZE - 1;
	for (j = 1; j <= i - 1; j++)		//找到要删除的元素的前一个位置
		k = L[k].cur;
	j = L[k].cur;		//获取要删除的元素
	L[k].cur=L[j].cur;		//将要删除的元素所指向的结点下标赋值给前一元素的后继
	Free_SSL(L, j);		//删除元素
	return 1;
静态链表的优缺点
  • 在插入和删除时,只需修改游标。(同单链表指针域)
  • 表长难以确定,需要足够大的空间

循环链表

  • 定义:将单链表中的终端结点的指针域由空指针改为指向头结点,这种头尾相接的单链表就叫做循环链表
  • 判断:p->next不等于头结点时,循环未结束。
  • 合并:通过尾指针合并两个循环链表A和B:
p = rearA->next;		//保存A的头节点
rearA->next = rearB->next->next;		//将B的第一个结点赋值给A的最后一个结点的后继
q = rearB->next;		//保存B的头结点
rearB->next = p;		//将A的头结点赋值给B的最后一个结点的后继
free(q);		//释放B的头结点

双向链表

  • 定义:在单链表的每个结点中,设置一个指向前驱结点的指针域则为双向链表
  • 双向链表也可以有循环。
双向链表的存储结构
typedef struct DulNode
{
	ElemType data;
	struct DuLNode *prior;		//直接前驱指针
	struct DuLNode *next;		//直接后继指针
}DulNode, *DuLinkList;
p->next->prior = p = p->prior->next;
//后继的前驱等于前驱的后继等于自己本身
双向链表的插入顺序
//在p后插入s
s->prior = p;		//把p赋值给s的前驱
s->next = p->next;		//把p后一个结点赋值给s的后继
p->next->prior = s;		//把s赋值给p的后一个结点的前驱
p->next = s;		//把s赋值给p的后继
双向链表的删除顺序
//删除p
p->prior->nex t= p->next;		//把p的后继赋值给p的前一个结点的后继
p->next->prior = p->prior;		//把p的前驱赋值给p的后一个结点的前驱
free(p);		//释放p
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值