更多精彩尽在微信公众号【程序猿声】
本节纲要
- 预备知识
- 顺序表(Sequential List)
- 单链表(Singly Linked List )
- 静态链表(Static list )
- 循环链表(circular linked list)
- 双向链表(doubly linked list)
05 循环链表
5.1什么是循环链表?
前面介绍了单链表,相信大家还记得相关的概念。其实循环链表跟单链表也没有差别很多,只是在某些细节上的处理方式会稍稍不同。
在此之前,大家可以先思考一个问题:单链表中,要找到其中某个节点只需要从头节点开始遍历链表即可,但是有些时候我们的想法是,能不能从任意节点开始遍历,也能找到我们需要的那个节点呢?
其实啊,这个实现也很简单自然,把整个链表串成一个环问题就迎刃而解了。所以,关于循环链表,我们有了如下的定义:
将单链表中的尾节点的指针域由NULL改为指向头结点,使整个单链表形成一个环,这种头尾相接的单链表就可以称之为**单循环链表,简称循环链表(circular linked list)。
5.2 循环链表图示
这里我们讨论的链表还是设置一个头结点(当然,链表并不是一定需要一个头结点)。
- 当链表为空的时候,我们可以有如下表示:
- 对于非空链表则可以这样表示:
-
不得不提的一点
对于循环链表这种设计,我们在遍历的时候的结束条件就不再是p为空的时候结束了。而是p等于头结点的时候遍历才完成。这一点希望大家切记。
-
再多说两句
我们知道,有了头结点,我们可以轻而易举访问第一个节点。但是当要访问最后一个节点时,却要将整个链表扫一遍,效率不可谓不低下……那么,有没有更好的办法呢?
当然是有的,只不过这里我们需要将循环链表再做一个小小的改进,具体表现为:
从上图可以看出,我们抛弃了以往的头指针,取而代之的是采用一个尾指针指向了最后一个节点。而且,因为链表是循环的,当我们需要访问第一个节点时,也very easy!只需要尾指针往后走一个就到前面了。
5.3 循环链表代码
关于循环链表的插入删除等操作,其实是和单链表一样的。唯一不同的就是遍历的时候的结束条件不同而已。因此咱们在这里就不做过多篇幅的介绍,直接贴完整代码吧。
循环链表就是末尾指向头形成一个循环的链表.实现思路也很简单,大体把单链表代码做个小小的改动就OK了.这次还是封装在一个类里面吧.
CircleLinkList.h 类头文件,各种声明定义
#pragma once //VC防止头文件重复包含的一条预编译指令
#define status bool
#define OK true
#define ERROR false
#define YES true
#define NO false
template <typename DType>
class Node
{
public:
DType data;
Node * pnext;
};
template <typename DType>
class CCircleLinkList
{
private:
Node<DType> *phead;
public:
CCircleLinkList();
~CCircleLinkList();
public:
//初始化链表
status InitCList();
//获取链表长度
int GetCListLength();
//增加一个节点 前插法
status AddCListNodeFront(DType idata);
//增加一个节点 后插法
status AddCListNodeBack(DType idata);
//判断链表是否为空
status IsCListEmpty();
//获取指定位置节点值(注意,本程序规定0号为头节点,e获取删除元素)
status GetCListIndexNode(DType *e, int index);
//删除指定位置节点(e获取删除元素)
status DeleteCListIndexNode(DType *e, int index);
//查找链表中指定值(pindex获取位置0==>not found)
status SearchCListNode(DType SData, int *pindex);
//指定位置前插
status InsertCListNodeFront(DType IData, int index);
//指定位置后插
status InsertCListNodeBack(DType IData, int index);
//清空链表(保留根节点)
status ClearCList();
//销毁链表(all delete)
status DestoryCList();
//尾部删除一个元素
status DeleteCListNodeBack();
//打印链表 此函数根据实际情况而定
void PrintCList();
};
CircleLinkList.cpp 类的具体实现代码
#include "CircleLinkList.h"
#include <stdio.h>
template <typename DType>
CCircleLinkList<DType>::CCircleLinkList()
{
cout << "链表创建" << endl;
InitCList();
}
template <typename DType>
CCircleLinkList<DType>::~CCircleLinkList()
{
cout << "链表销毁" << endl;
DestoryCList();
}
//初始化链表
template <typename DType>
status CCircleLinkList<DType>::InitCList()
{
Node