【数据结构】循环链表&&双向链表详解和代码实例

本文详细介绍了循环链表和双向链表的概念、图示、存储结构以及插入和删除操作。循环链表通过将尾节点指向头节点形成环状,便于从任意节点开始遍历。双向链表则在每个节点增加一个指针域指向前驱节点,允许双向遍历。文章提供了相关的代码实例。
摘要由CSDN通过智能技术生成

喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号【程序猿声】

01 循环链表

1.1 什么是循环链表?

前面介绍了单链表,相信大家还记得相关的概念。其实循环链表跟单链表也没有差别很多,只是在某些细节上的处理方式会稍稍不同。

在此之前,大家可以先思考一个问题:单链表中,要找到其中某个节点只需要从头节点开始遍历链表即可,但是有些时候我们的想法是,能不能从任意节点开始遍历,也能找到我们需要的那个节点呢?

其实啊,这个实现也很简单自然,把整个链表串成一个环问题就迎刃而解了。所以,关于循环链表,我们有了如下的定义:

将单链表中的尾节点的指针域由NULL改为指向头结点,使整个单链表形成一个环,这种头尾相接的单链表就可以称之为**单循环链表,简称循环链表(circular linked list)。

1.2 循环链表图示

这里我们讨论的链表还是设置一个头结点(当然,链表并不是一定需要一个头结点)。

  • 当链表为空的时候,我们可以有如下表示:
  • 对于非空链表则可以这样表示:
  • 不得不提的一点

    对于循环链表这种设计,我们在遍历的时候的结束条件就不再是p为空的时候结束了。而是p等于头结点的时候遍历才完成。这一点希望大家切记。

  • 再多说两句

    我们知道,有了头结点,我们可以轻而易举访问第一个节点。但是当要访问最后一个节点时,却要将整个链表扫一遍,效率不可谓不低下……那么,有没有更好的办法呢?

    当然是有的,只不过这里我们需要将循环链表再做一个小小的改进,具体表现为:

    从上图可以看出,我们抛弃了以往的头指针,取而代之的是采用一个尾指针指向了最后一个节点。而且,因为链表是循环的,当我们需要访问第一个节点时,也very easy!只需要尾指针往后走一个就到前面了。

1.3 循环链表代码

关于循环链表的插入删除等操作,其实是和单链表一样的。唯一不同的就是遍历的时候的结束条件不同而已。因此咱们在这里就不做过多篇幅的介绍,直接贴完整代码吧。

循环链表就是末尾指向头形成一个循环的链表.实现思路也很简单,大体把单链表代码做个小小的改动就OK了.这次还是封装在一个类里面吧.

CircleLinkList.h 类头文件,各种声明定义

 1#pragma once //VC防止头文件重复包含的一条预编译指令
2
3#define status bool
4#define OK true
5#define ERROR false
6#define YES true
7#define NO false
8
9template <typename DType>
10class Node
11{

12public:
13    DType data;
14    Node * pnext;
15};
16template <typename DType>
17class CCircleLinkList
18{

19private:
20    Node<DType> *phead;
21public:
22    CCircleLinkList();
23    ~CCircleLinkList();
24public:
25    //初始化链表
26    status InitCList();
27    //获取链表长度
28    int GetCListLength();
29    //增加一个节点 前插法
30    status AddCListNodeFront(DType idata);
31    //增加一个节点 后插法
32    status AddCListNodeBack(DType idata);
33    //判断链表是否为空
34    status IsCListEmpty();
35    //获取指定位置节点值(注意,本程序规定0号为头节点,e获取删除元素)
36    status GetCListIndexNode(DType *e, int index);
37    //删除指定位置节点(e获取删除元素)
38    status DeleteCListIndexNode(DType *e, int index);
39    //查找链表中指定值(pindex获取位置0==>not found)
40    status SearchCListNode(DType SData, int *pindex);
41    //指定位置前插
42    status InsertCListNodeFront(DType IData, int index);
43    //指定位置后插
44    status InsertCListNodeBack(DType IData, int index);
45    //清空链表(保留根节点)
46    status ClearCList();
47    //销毁链表(all delete)
48    status DestoryCList();
49    //尾部删除一个元素
50    status DeleteCListNodeBack();
51    //打印链表   此函数根据实际情况而定
52    void PrintCList();
53};

CircleLinkList.cpp 类的具体实现代码

  1#include "CircleLinkList.h"
2
3#include <stdio.h>
4
5template <typename DType>
6CCircleLinkList<DType>::CCircleLinkList()
7{
8    cout << "链表创建" << endl;
9    InitCList();
10}
11
12template <typename DType>
13CCircleLinkList<DType>::~CCircleLinkList()
14{
15    cout << "链表销毁" << endl;
16    DestoryCList();
17}
18
19
20//初始化链表
21template <typename DType>
22status CCircleLinkList<DType>::InitCList()
23{
24    Node<DType> * ph = new Node<DType>;
25    if (ph != NULL)
26    {
27        ph->pnext = ph;    //尾指向头
28        this->phead = ph; //头结点
29        return OK;
30    }
31
32    return ERROR;
33
34}
35
36//获取链表长度(head_node is not included)
37template <typename DType>
38int CCircleLinkList<DType>::GetCListLength()
39{
40    int length = 0;
41    Node<DType> * ph = this->phead;
42    while (ph->pnext != this->phead)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值