线性表链式结构的扩展(循环链表和双向链表)

数据结构与算法第二章(线性表的链式结构中的循环链表与双向链表)

循环链表

循环链表,是指链表的最后一个结点的指针域指向头结点,使得链表头尾结点相连,从而形成一个环。
其基本功能操作与单链表类似,唯一不同指出在于判断链表是否结束时,不在为判断结点的指针域是否为空,而是判断结点是否指向头结点。也就是:

while(p->Next != L)

另外,循环链表可以从链表的任意位置开始遍历链表,得到的结果都是完整的链表

双向链表

在之前对单链表进行删除的时候,我们用到了两个指针以及两层循环去解决,这样导致空间与时间上的浪费,而双向链表便可以轻松的解决这个问题。在这里,我们定义每个节点除了数据域data外,包含了两个不同的指针,一个指针名叫prior,指向它的前驱结点;另一个名叫next,指向它的后继结点,所以双向链表的定义如下:

typedef struct LNode{
	ELemType data;
	struct LNode *piror,*next;
}LNode;

由于双向链表的指针定义,我们得出:

	p->next->prior <=> p;			//假设p是LinkList型指针,<=>为两边都等价
	p->prior->next <=> p;

由于双向链表的指针的特殊性,它的基本操作与单链表有所不同,以下为双向链表的基本操作:
1.初始化

Status InitList(LinkList &L)
{
	if(L == NULL)
		return 0;
	L = (LinkList *)malloc(sizeof(LNode));
	L->next = NULL:
	L->prior = NULL;					//使前驱指针与后继指针均初始化为空
	return 1;
}

2.创建链表

Status CreateList(LinkList &L,int m)
{
	InitList(L);
	LinkList p;	
	p = L;								//定义LinkList类型的指针q,并使q指向p
	for(int i = 0;i < m;i++)
	{
		LinkList q;
		q = (LinkList *)malloc(sizeof(LNode));			//定义LinkList类型的指针p
		q->data = rand()%100+1;							//赋予q->data一个随机数
		q->prior = p;									//先使q的前驱指针指向p,也就是指向头结点
		q->next = NULL;									//使q的后继指针初始化为空
		p->next = q;									//p的后继指针指向q
		p=q;											//p向后移动一个位置
	}
}

插入指针的顺序为:
(1)先赋给q->data数值
(2)使q的前驱指针指向p,也就是指向头结点
(3)使q的后继指针初始化为空,这步至关重要,它影响后续的插入,如果不初始化为空,q->next将成为野指针
(4)p的后继指针指向q
(5)p向后移动一个位置,进行下一次插入

3.双向链表的遍历与单链表相同

4.删除指定位置的数

Status DeleteLinkList_D(LinkList &L,int i,ElemType &e)
{
	LinkList p;
	int n =0;
	while(p != NULL && n<i)
	{
		p=p->next;
		n++;
	}
	if(p=NULL || n>i)
		return 0;
	e = p->data;
	p->prior->next = p->next;						//将p之前一个元素的后继指针指向p的下一个元素
	p->next->prior = p->prior;						//将p之后的元素的前置指针指向p的前一个元素
													//此时p彻底被切断
	free(P);										//将指针p释放
	return 1;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值