学习笔记——链表操作中的前驱插入与后继插入(代码分析)(系列持续更新,但每篇都很短)

链表前驱后继插入

概念解析

原因来自我现在自学数据结构与算法,非科班靠着网课自学有点吃力,不过也只能这样了,毕竟考研也不读计算机,只是觉得必须要学好这些知识而已。
回归正题,这是我在学习他人代码时候得到的一些知识想法或者经验,仅作分享,就那种恍然大悟的感觉,你懂吧?
好了,正题正题,我在看了清华大学邓老师的数据结构(不得不说代码是真的吹,看了好久恍然大悟,惊叹如此简单巧妙),有一部分代码不解,思考甚久,终于得到一个过程,或者该说设计逻辑。这部分就在以下的代码分析同步进行。

代码分析

typedef int Rank; //秩
#define ListNodePosi(T) ListNode<T>* //列表节点位置

template <typename T> struct ListNode { //列表节点模板类(以双向链表形式实现)
// 成员
   T data; ListNodePosi(T) pred; ListNodePosi(T) succ; //数值、前驱、后继
// 构造函数
   ListNode() {} //针对header和trailer的构造
   ListNode ( T e, ListNodePosi(T) p = NULL, ListNodePosi(T) s = NULL )
      : data ( e ), pred ( p ), succ ( s ) {} //默认构造器
 // 操作接口
   ListNodePosi(T) insertAsPred ( T const& e ); //紧靠当前节点之前插入新节点
   ListNodePosi(T) insertAsSucc ( T const& e ); //紧随当前节点之后插入新节点

以上是链表节点类的构造函数部分(类未完全截取,没必要),关注点在构造函数上,这里使用列表初始化方式,记住这点,再来看下面的

template <typename T> ListNodePosi(T) List<T>::insertA ( ListNodePosi(T) p, T const& e )
{  _size++; return p->insertAsSucc ( e );  } //e当作p的后继插入(After)

以上为在某节点后继部分插入新节点的函数,注意最后的return部分,它所返回的是一个节点,而p是当前操作的节点位置,对p进行函数操作代码如下:

template <typename T> //将e紧随当前节点之后插入于当前节点所属列表(设有哨兵尾节点trailer)
ListNodePosi(T) ListNode<T>::insertAsSucc ( T const& e ) 
{
 	ListNodePosi(T) x = new ListNode ( e, this, succ ); //创建新节点
 	succ->pred = x; succ = x; //设置逆向链接
 	return x; //返回新节点的位置
 }

这只是其中一种操作方式,相当巧妙的地方是,创建新节点,但在初始化的时候,将新节点的前驱初始化为this指针,也就是当前操作的p指针,而后继则是p指针的后继,接下来则是将p的后继的前驱改为指向新节点x,然后p指针的后继再改为指向新节点x,最后返回x节点的位置,这直接用简易的代码做好了插入的操作,令初学者不得不惊叹如此老练的写法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杜景今天吃雪糕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值