使用循环链表实现一个通讯录的管理程序_每天5分钟用C#学习数据结构(7)循环链表 Part 1...

45ed10bc9476cf695327b5aa395b5234.png

【基础知识】| 作者 / Edison Zhou

这是恰童鞋骚年的第192篇原创文章


上一篇介绍了双链表的实现,这一篇我们来学习下循环链表。

1循环链表的基础

循环链表的节点结构

dd40cbba9d95f3474e6073ef7564927c.png

循环链表和单链表的主要差异就在于循环的判断条件上,原来是判断p.next是否为空,现在则是p.next不等于头结点,则循环未结束。

循环链表的O(1)访问时间

在单链表中,有了头结点,我们可以在O(1)时间访问到第一个节点,但如果要访问最后一个节点却需要O(n)的时间,因为我们需要对整个链表进行一次遍历。在循环链表中,我们可以借助尾节点来实现,即不用头指针,而是用指向终端结点的尾指针来表示循环链表,这时候无论是查找第一个节点还是最后一个节点都很方便,可以控制在O(1)的时间内,如下图所示。

0fffff136eb2ef1b6798bb90310cbfa7.png

从上图中可以看到,终端结点用尾指针(tail)指示,则查找终端结点是O(1),而开始结点,其实就是tail.Next,其时间复杂也为O(1)。由此也可以联想到,在合并两个循环链表时,只需要修改两个链表的尾指针即可快速地进行合并。

2循环链表的实现

Talk is cheap, show me the code。多说无益,开始用C#来实现一个吧。

循环链表的节点定义实现

public class CirNode{    public T Item { get; set; }    public CirNode Next { get; set; }    public CirNode(){    }    public CirNode(T item){        this.Item = item;    }}

这里跟单链表的节点定义实现并无区别。

循环链表的新节点插入

public void Add(T value){    CirNode newNode = new CirNode(value);    if (this.tail == null)    {        // 如果链表当前为空则新元素既是尾头结点也是头结点        this.tail = newNode;        this.tail.Next = newNode;        this.currentPrev = newNode;    }    else    {        // 插入到链表末尾处        newNode.Next = this.tail.Next;        this.tail.Next = newNode;        // 改变当前节点        if (this.currentPrev == this.tail)        {            this.currentPrev = newNode;        }        // 重新指向新的尾节点        this.tail = newNode;    }    this.count++;}

首先,这里的currentPrev字段是使用了前驱节点来标识当前节点,如要获取当前节点的值可以通过currentPrev.Next.Item来获得。其次,在最后将尾节点指针指向新插入的节点。

3小结

本文介绍了循环链表的定义及如何实现循环链表的节点与新节点插入。下一篇,我们将要继续学习循环链表的节点移除及完整DEMO测试。

4参考资料

程杰,《大话数据结构》

陈广,《数据结构(C#语言描述)》

段恩泽,《数据结构(C#语言版)》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值