C语言中特殊结构类型“双链表”

本文介绍了双向链表的概念,区别于单链表,双向链表每个节点包含两个指针,分别指向前一个和后一个节点,允许双向遍历。文章详细讨论了双向链表的定义、操作,并通过代码示例解释了插入节点的过程。
摘要由CSDN通过智能技术生成

前面写了一篇文章《C语言中特殊结构类型“单链表”》,既然有单链表,那就会有双链表。所以,我想来详谈一下双链表。

双向链表,顾名思义,其有别于单向链表。单向链表是有方向的,其方向是从头结点开始,直到尾结点。实质是因为单链表的指针域只存储了下一结点的地址。而双链表之所以是双向,其实质也就是每个结点的指针域不仅存储下一结点的地址,还存储上一结点的地址。

这有什么好处吗?想想看假设对于一个单向链表,某一结点的后继结点可以直接通过next指针找到,但是如果我要你找这个结点的前继结点,是不是很困难?因为这一结点并未提供前一结点的任何信息。双向链表的引入轻而易举地解决这类问题。

概念:双向链表就是链表方向是双方向的,也就是双向链表中的每一个结点的指针域有两个指针,一个指针用来指向上一个结点(Previous指针),另一个指针用指向下一个结点(Next指针)。

 

双向链表示意图
通过这个图,找找双向链表与单向链表的共性和差异?

共性:单向链表和双向链表均有头结点。且头结点中只有数据域和指向首元结点的next指针。此外,其他结点都有数据域。双向结点从头指针向右的方向看其实就是单向指针。且最后一个结点的指针域为空,即NULL。

差异:双向链表除头结点外,其他结点的指针域不但包含后继结点的地址,还包含前驱结点的地址。(第一个结点的指针域没有前驱指针,最后一结点没有后继指针),总而言之,双向链表结点只是比单向链表结点多了一个前驱单元指针,用于找到前驱结点。与单向链表相比,双向链表具有反向遍历的功能。

定义:

typedef struct DNode * PtrToDNode;
struct DNode  //与定义单向链表的模板一同
{
   ElementType Data; //存储结点数据
   PtrToDNode Next;     //指向下一个结点的指针
   PtrToDNode previous;    //指向前一个结点的指针
};

通过这个代码,找找双向链表与单向链表的共性和差异?

共性:因为都是定义结点,所以模板与单向链表一样,结构成员包括数据域和指针域。

差异:多定义一个指针,这个指针用于保存前驱结点的地址。也就是说不但有next指针,还有pre指针。

操作

双向链表有哪些操作呢?是不是和单向链表有一样的操作呢?

答:双向链表也有插入,删除,遍历的操作。

我们在考虑这些操作的时候应该考虑哪些问题呢?

首先,因为双向链表的指针域有前后两个指针,所以需要同时考虑这两个指针。

下面我们以双向链表的插入为例先来看一个简单的例子。

//假设现在有一个双向链表,要在p指针指向的a2结点后插入新结点t,应该怎么做呢?
//要插入一个结点t,大概思路是:新插入的结点的前驱指针应该指向a2,即保存a2的地址。后继指针应该指向a3,即保存a3的地址
t---->previous = p;
t---->next = p---->next;  //p---->next实际上是a3的地址,把它保存到t的指针域的后继指针
p---->next---->previous = t;  //p---->next为结点a3,它的前驱指针指向t
p---->next = t;              //p的后继指针指向t
//在增加结点t的同时,不忘更改a2的后继指针和a3的前驱指针

通过上述代码,我们发现要在一个双向链表中增加一个结点,大致有两步:首先要在新结点的指针域增加前驱指针和后继指针;然后要修改增加结点的后一个结点的前驱指针,和前一个结点的指针域的后继指针。而且要注意上述语句要保持一定的顺序。否则得不到正确的结果。

//假设现在要删除p指向的a2结点,应该怎么做呢?
p---->previous---->next = p---->next;//把a3的地址存放到a1的后继指针域
p---->next---->previous = p---->previous;//把a1的地址赋值给a3的前继指针
free(p);

由于双向链表具有反向遍历的功能,所以它可以从尾结点开始向前遍历。

 

以上,就是对双向链表的浅谈。

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值