循环链表的一个C++实现
下面是循环链表的一个C++实现,参考了《数据结构与算法分析C语言版》及不少牛人的分析总结,在此一并感谢了。在VC2005上经反复验证试验,结果非常不错。这是一个比较简易的实现,让其继承自单链表,并提供了一个专为解决约瑟夫问题的函数(RemoveAt)。以后将会开发一个更一般性的版本。
注意:单链表及双向及循环链表均不使用表头(即哑节点,dummy node), 即m_pNodeHead指向链表的第一个真正的节点。
单链表类SList的实现见本博客的文章《单链表的一个C++实现》。
/*clist.h*/
#include "slist.h"
/*一般而言,将循环链表继承自单向链表,会有一些问题的:
1.作为基类的单向链表的析构函数应该为虚函数,因为作为有多态性质的基类的析构函数必须是virtual的;
2.循环列表中重定义了函数RemoveAt,一般情况下绝对不应该重定义基类中的非虚函数的,因为会导致精神分裂症:通过指向或应用循环列表
的基类指针或引用来调用该函数时,会调用基类中RemoveAt,而通过循环列表本身或指向或引用它的派生类指针或引用调用该函数时,会调用
派生类中的RemoveAt。
但是,如果不适用多态性质,也就是不通过基类的指针或引用来操纵派生类对象的情况下,上述两个问题是不会爆发出来的!*/
template<typename T>
class CList : public SList<T>
{
protected:
Node<T> *m_pNodeCurr;
public:
CList();
public:
T& GetNext();
void RemoveAt(const int pos);
int GetCurrentIndex() const;
};
template<typename T>
inline CList<T>::CList() : m_pNodeCurr(NULL)
{
}
/*这个函数很重要。循环链表是概念上的,实际上链表的最后一个节点并未指向其头节点。循环链表的概念是靠该函数来实施的。
如果当前节点为NULL或者当前节点为最后一个节点,则将其调整为指向头节点,否则将其向后移动一个节点;
然后返回当前节点的数据。*/
template<typename T>
inline T& CList<T>::GetNext()
{
ASSERT(0 != m_nCount);
if ((NULL == m_pNodeCurr) || (NULL == m_pNodeCurr->next))
m_pNodeCurr = m_pNodeHead;
else
m_pNodeCurr = m_pNodeCurr->next;
return m_pNodeCurr->data;
}
//返回当前节点的位置。
template<typename T>
inline int CList<T>::GetCurrentIndex() const
{
ASSERT(0 != m_nCount);
int i;
Node<T> *pTmpNode = m_pNodeHead;
for (i = 1; i <= m_nCount; ++i)
{
if (pTmpNode == m_pNodeCurr)
return i;
else
pTmpNode = pTmpNode->next;
}
return 0;
}
//删除一个节点,就让当前节点指向其前一个节点;如果删除的是头节点,则应将当前节点置为NULL。
//这个函数似乎专为解决约瑟夫问题而设计的。
template<typename T>
inline void CList<T>::RemoveAt(const int pos)
{
ASSERT(1 <= pos && pos <= m_nCount);
int i;
Node<T> *pTmpNode1;
Node<T> *pTmpNode2;
pTmpNode1 = m_pNodeHead;
// head node?
if (1 == pos)
{
m_pNodeHead = m_pNodeHead->next;
// added for loop list
// m_pNodeCurr will be set to m_pNodeHead in function GetNext()
m_pNodeCurr = NULL;
delete pTmpNode1;
--m_nCount;
return;
}
for (i = 1; i < pos; ++i)
{
// we will get the previous node of the target node after
// the for loop finished, and it would be stored into pTmpNode2
pTmpNode2 = pTmpNode1;
pTmpNode1 = pTmpNode1->next;
}
pTmpNode2->next = pTmpNode1->next;
// added for loop list
m_pNodeCurr = pTmpNode2;
delete pTmpNode1;
--m_nCount;
return;
}
循环链表的一个C++实现相关推荐
- 使用循环链表实现一个通讯录的管理程序_【LeetCode链表题型总结】
点击上方蓝字,关注公众号 链表概念的讲解 链表是什么 链表是一种线性数据结构,每个节点都存有数据,通过指针将各个节点链接在一起. 链表的性质 一致性: 每个节点有相同的数据结构,相同的数据大小,内存中 ...
- 【数据结构与算法】之单向循环链表的创建/遍历/插⼊/查找/删除算法实现
一.单向循环链表简介 单向循环链表是一个收尾相接的链表,将单链表的最后一个指针域改由NULL改为指向表头结点这就是单链式的循环链表,并称为循环单链表. 带头结点的循环单链表的各种操作的算法实现与带头结 ...
- 数据结构基础(11) --循环链表的设计与实现
循环链表:最后一个结点的指针域的指针又指回第一个结点的链表; 循环单链表与单链表的区别在于:表中最有一个节点的指针不再是NULL, 而改为指向头结点(因此要对我们原来的MyList稍作修改), 从而整 ...
- 双向循环链表中结点的交换(C++)
描述 利用双向循环链表表示一个整数序列,指定一个结点位置用p指向该结点,交换p所指向的结点及其前驱结点的顺序. 输入 多组数据,每组数据有三行,第一行为链表的长度n,第二行为链表的n个元素(元素之间用 ...
- 单、双链表的循环链表(十五)
1. 单链表的循环链表 <1>.单链表的循环链表特点 单链表只能向后操作,不能向前操作,如果从当前结点开始,无法访问该结点前面的结点. 如果最后一个结点的指针指向头节点,形成一个闭环,就可 ...
- circular linked listCLL(循环链表)
循环链表,和苯一样,一条蛇咬住了自己的尾巴.在 操作系统 给 进程 分配运行 资源 时,有体现. 1 #include<stdio.h> 2 #include<stdlib.h> ...
- 【循环链表】数据结构——单向循环链表和双向循环链表操作笔记
循环链表 一.单向循环链表 1.单向循环链表的节点 2.单向循环链表的结构 二.双向循环链表 1.双向循环链表示意图 2.双向循环链表节点设计 3.双向循环链表的一般性结构 4.双向循环链表头插法插入 ...
- 【数据结构】循环链表
文章目录 1.概念 2.循环链表的头文件与函数声明 3.函数实现 3.1 购买节点 3.2 初始化函数(重点) 3.3 判空函数 3.4 获取有效数据个数 3.5 头插函数 3.6尾插(重点) 3.7 ...
- Java中的循环链表
与链表相比,循环链表略有不同.在循环链表中,最后一个节点指向第一个节点,从而完成一整圈节点.换句话说,我们也可以说在这个链表中,最后一个元素不是空的.在这种类型的链表中,任何节点都可以作为起点.这意味 ...
最新文章
- git获取提交记录commit id
- a站手机访问电脑版_公司电脑一键变网盘,支持手机、家里电脑远程访问
- Android之Badge显⽰
- Quartz以及代码实现--可以实现定时器效果
- vc/vs开发的应用程序添加dump崩溃日志转
- 【转】博客美化(3)为博客添加一个漂亮的分享按钮
- TensorFlow 的简化接口Scikit Flow
- linux定时器编程实验报告,Linux定时器实验.doc
- Xshell使用方法
- springboot中ehcache的使用
- 在线qq客服的html代码生成器,js生成qq客服在线代码
- Linux内存从0到1学习笔记(3,高速缓存)
- 官方股票交易接口怎么查询股票历史数据?
- python3d动画效果_使用Matplotlib 3D实现三维波浪动画
- SONET/SDH技术讲解
- FL STUDIO 21中文版已经发布啦,有什么新功能?
- 融云IM商用版冰点促销 助程序员的十二时辰躺赢
- SpringCloud从入门到精通教程/SpringCloud Alibaba从入门到精通教程
- 进制转换(任意进制转换)
- 人工智能合一算法java语言实现_人工智能合一算法UNify.doc