CTDChain<T,sort,equal,pointer> * nodeTemp = NULL;
------------------------------------------------------------------------------
using namespace std;
//双向不循环链表
//sort 指示是否有序
//equal 指示当出现相同节点时的处理方法
//pointer 指示是否是一个指针类型,在析构时必不可少
template <class T,
const int sort = 0,
const CtEqualMethod equal = CtEM_ALLOW,
const int pointer = 1>
--------------------------------------------------------------------------------------
class CTDChain
{
public:
CTDChain * m_pPrev;
CTDChain * m_pNext;
T m_tItem;
protected:
// 向链表头搜索一个节点, 失败时返回空指针,direct指示搜索方向
virtual CTDChain * SearchPrev(T &item)
{
if( TypeComp(m_tItem,item, CtCS_EQ) ) return this;
else if( m_pPrev )
return m_pPrev->CTDChain<T,sort,equal,pointer>:: SearchPrev(item);
else return NULL;
}
// 向链表尾部搜索一个节点, 失败时返回空指针,direct指示搜索方向
virtual CTDChain * SearchNext(T &item)
{
if( TypeComp(m_tItem,item, CtCS_EQ) ) return this;
else if( m_pNext )
return m_pNext->CTDChain<T,sort,equal,pointer>:: SearchNext(item);
else return NULL;
}
//从本节点开始向后查找最小的节点,由排序函调用
virtual CTDChain * SmallestNext()
{
CTDChain<T,sort,equal,pointer> * nodeNext = m_pNext;
CTDChain<T,sort,equal,pointer> * nodeSmall = this;
while( nodeNext )
{
if( nodeSmall->m_tItem > nodeNext->m_tItem ) nodeSmall = nodeNext;
nodeNext = nodeNext->m_pNext;
}
return nodeSmall;
}
public:
CTDChain(): m_pPrev(0), m_pNext(0), m_tItem(0){};
CTDChain(T &item): m_pPrev(0), m_pNext(0), m_tItem(0)
{
CTDChain<T,sort,equal,pointer>:: SetNodeItem(item);
}
//考贝构造函数
CTDChain(CTDChain & node)
{
m_pPrev = node.m_pPrev;
m_pNext = node.m_nNext;
if( pointer )
{
if( !m_tItem ) m_tItem = new T;
*m_tItem = *(node.nodeItem);
}
else m_tItem = node.nodeItem;
}
//析构时自动删除在它后面的节点
~CTDChain()
{
if( pointer && m_tItem ) delete m_tItem;
if( m_pPrev ) m_pPrev->m_pNext = NULL;
if( m_pNext )
{
m_pNext->m_pPrev = NULL;
delete m_pNext;
m_pNext = NULL;
}
}
// 找到链表头节点
CTDChain * Head()
{
if( !m_pPrev ) return this;
else return m_pPrev->CTDChain<T,sort,equal,pointer>:: Head();
}
// 找到链表尾节点
CTDChain * Tail()
{
if( !m_pNext ) return this;
else return m_pNext->CTDChain<T,sort,equal,pointer>:: Tail();
}
//统计链表中节点个数
int NodeNum()
{
int nNum = 0;
CTDChain<T,sort,equal,pointer> * nodeTemp = Head();
while( nodeTemp )
{
nNum++;
nodeTemp = nodeTemp->m_pNext;
}
return nNum;
}
//从链表中移走一个节点
//注意:Pop头节点时,要有指针记录新的头节点
virtual void Pop()
{
if( m_pPrev ) m_pPrev->m_pNext = m_pNext;
if( m_pNext ) m_pNext->m_pPrev = m_pPrev;
m_pPrev = m_pNext = NULL;
}
//设置一个节点的值,替换掉原有的值
virtual int SetNodeItem(const T &item)
{
if( pointer && m_tItem ) delete m_tItem;
m_tItem = item;
return CtRC_REPLACE;
}
int TypeComp(const T &a, const T&b, CtCompartStyle style = CtCS_GT)
{
if( pointer )
{
switch( style )
{
case CtCS_GT: return ((*a) > (*b)); break;
case CtCS_GE: return ((*a) >= (*b)); break;
case CtCS_EQ: return ((*a) == (*b)); break;
case CtCS_NE: return ((*a) != (*b)); break;
case CtCS_LT: return ((*a) < (*b)); break;
case CtCS_LE: return ((*a) <= (*b)); break;
default: return 0;
}
}
else
{
switch( style )
{
case CtCS_GT: return (a > b); break;
case CtCS_GE: return (a >= b); break;
case CtCS_EQ: return (a == b); break;
case CtCS_NE: return (a != b); break;
case CtCS_LT: return (a < b); break;
case CtCS_LE: return (a <= b); break;
default: return 0;
}
}
return 1;
}
// 搜索一个节点, 失败时返回空指针
virtual CTDChain * Search(T &item)
{
CTDChain<T,sort,equal,pointer> * nodeTemp = NULL;
if( TypeComp(m_tItem,item,CtCS_EQ) ) return this;
if( sort )
{//有序
if( TypeComp(item,m_tItem) ) nodeTemp = CTDChain<T,sort,equal,pointer>:: SearchNext(item);
else nodeTemp = CTDChain<T,sort,equal,pointer>:: SearchPrev(item);
}
else
{//无序
nodeTemp = CTDChain<T,sort,equal,pointer>:: SearchPrev(item);
if( !nodeTemp ) nodeTemp = CTDChain<T,sort,equal,pointer>:: SearchNext(item);
}
return nodeTemp;
}
//插入一个节点在本节点之前,node必须是一个单节点
virtual int PushPrev(CTDChain * node)
{
node->m_pNext = this;
node->m_pPrev = m_pPrev;
if( m_pPrev ) m_pPrev->m_pNext = node;
m_pPrev = node;
return CtRC_SUCCESS;
}
//插入一个节点在本节点之后,node必须是一个单节点
virtual int PushNext(CTDChain * node)
{
node->m_pNext = m_pNext;
node->m_pPrev = this;
if( m_pNext ) m_pNext->m_pPrev = node;
m_pNext = node;
return CtRC_SUCCESS;
}
//插入一个单节点
virtual int Push(CTDChain * &node)
{
CTDChain<T,sort,equal,pointer> * nodeTemp;
if( !node ) return CtRC_FAIL;
//判断相同节点
switch( equal )
{
case CtEM_REJECT: //不允许出现相同节点
case CtEM_REPLACE: //替换相同节点
nodeTemp = CTDChain<T,sort,equal,pointer>:: Search(node->m_tItem);
if( NULL == nodeTemp ) break;
if( equal == CtEM_REJECT ) return CtRC_REJECT;
return nodeTemp->CTDChain<T,sort,equal,pointer>:: SetNodeItem(node->m_tItem);
break;
case CtEM_ALLOW: //允许出现相同节点
default:
break;
}
//查找插入点,这里不用考虑相等情况
nodeTemp = this;
if( sort )
{//有序
if( TypeComp(node->m_tItem,nodeTemp->m_tItem) )
{//向表尾查找
while( TypeComp(node->m_tItem,nodeTemp->m_tItem) )
{
if( !nodeTemp->m_pNext ) break;
nodeTemp = nodeTemp->m_pNext;
}
}
else
{//向表头查找
while( TypeComp(nodeTemp->m_tItem,node->m_tItem) )
{
if( !nodeTemp->m_pPrev )
return nodeTemp->CTDChain<T,sort,equal,pointer>:: PushPrev(node);
nodeTemp = nodeTemp->m_pPrev;
}
}
}
else
{//无序
nodeTemp = CTDChain<T,sort,equal,pointer>:: Tail();
}
//在上面还有一个插入点,是插入在链表的头部
return nodeTemp->CTDChain<T,sort,equal,pointer>:: PushNext(node);
}
virtual int Push(T &item)
{
CTDChain<T,sort,equal,pointer> * nodeTemp;
int nRet;
if( NULL == (nodeTemp = new CTDChain<T,sort,equal,pointer>(item)) )
{
RAISE_ERROR("警告:申请内存失败");
return CtRC_FAIL;
}
nRet = CTDChain<T,sort,equal,pointer>:: Push(nodeTemp);
switch( nRet )
{
case CtRC_FAIL: break;
case CtRC_SUCCESS: break;
case CtRC_REPLACE:
if( pointer ) nodeTemp->m_tItem = NULL;
case CtRC_REJECT:
delete nodeTemp;
break;
default: break;
}
return nRet;
}
//插入另外一个链表的所有节点,返回值是插入节点的个数
//插入完成后,原链表被删除
virtual int Merge(CTDChain * &chain)
{
CTDChain<T,sort,equal,pointer> * nodeTemp;
int nRet, nNum = 0;
if( !chain ) return 0;
//先截断原链表
if( chain->m_pPrev )
{
chain->m_pPrev->m_pNext = NULL;
chain->m_pPrev = NULL;
}
//如果允许相同节点且无序
if( equal == CtEM_ALLOW && !sort )
{
nNum = chain->NodeNum();
nodeTemp = CTDChain<T,sort,equal,pointer>:: Tail();
nodeTemp->m_pNext = chain;
chain->m_pPrev = nodeTemp;
}
else
{
nodeTemp = chain;
while( nodeTemp )
{
chain = chain->m_pNext;
nodeTemp->Pop();
nRet = CTDChain<T,sort,equal,pointer>:: Push(nodeTemp);
switch( nRet )
{
case CtRC_SUCCESS: nNum++; break;
case CtRC_REPLACE:
if( pointer ) nodeTemp->m_tItem = NULL;
case CtRC_REJECT:
case CtRC_FAIL:
delete nodeTemp;
break;
default: break;
}
nodeTemp = chain;
}
}
chain = NULL;
return nNum;
}
//排序函数, 它使用T的操作符 '>'
virtual void Sort()
{
CTDChain<T,sort,equal,pointer> * nodeSmall;
CTDChain<T,sort,equal,pointer> * nodeTemp = CTDChain<T,sort,equal,pointer>:: Head();
while( nodeTemp )
{
nodeSmall = nodeTemp->CTDChain<T,sort,equal,pointer>:: SmallestNext();
if( nodeSmall != nodeTemp )
{//最小节点不是当前节点
nodeSmall->CTDChain<T,sort,equal,pointer>:: Pop();
nodeTemp->CTDChain<T,sort,equal,pointer>:: PushPrev(nodeSmall);
}
else nodeTemp = nodeTemp->m_pNext;
}
}
- Redis list实现原理 - 双向循环链表
双向链表 双向表示每个节点知道自己的直接前驱和直接后继,每个节点需要三个域 查找方向可以是从左往右也可以是从右往左,但是要实现从右往左还需要终端节点的地址,所以通常会设计成双向的循环链表; 双向的循环 ...
- Dancing Links 模板
struct dl{ // x: line, y: column struct node{ int c, left, right, up, down; }; vector<node> a; ...
- 通过例子进阶学习C++(七)CMake项目通过模板库实现约瑟夫环
本文是通过例子学习C++的第七篇,通过这个例子可以快速入门c++相关的语法. 1.问题描述 回顾一下约瑟夫环问题:n 个人围坐在一个圆桌周围,现在从第 s 个人开始报数,数到第 m 个人,让他出局:然 ...
- 侯捷STL学习(一)
开始跟着<STL源码剖析>的作者侯捷真人视频,学习STL,了解STL背后的真实故事! 视频链接:侯捷STL 还有很大其他视频需要的留言 第一节:STL版本和重要资源 STL和标准库的区别 ...
- 侯捷STL课程及源码剖析学习1
1.C++标准库和STL C++标准库以header files形式呈现: C++标准库的header files不带后缀名(.h),例如#include <vector> 新式C hea ...
- 侯捷STL学习(一)--顺序容器测试
开始跟着<STL源码剖析>的作者侯捷真人视频,学习STL,了解STL背后的真实故事! 视频链接:侯捷STL 还有很大其他视频需要的留言 第一节:STL版本和重要资源 STL和标准库的区别 ...
- 详解DLX及其应用
什么是DLX? 让我们看看百度百科上的解释:在 计算机科学 中, Dancing Links ,舞蹈链, 也叫 DLX, 是由 Donald Knuth 提出的数据结构,目的是快速实现他的 X算法.X ...
- Josephus环类问题,java实现
写出一个双向的循环链表,弄一个计数器,我定义的是到三的时候,自动删除当前节点,很简单. package Com; import java.util.Scanner; /* * 约瑟夫环问题,有n个人组 ...
- Redis入门指南(第2版) Redis设计思路学习与总结
https://www.qcloud.com/community/article/222 宋增宽,腾讯工程师,16年毕业加入腾讯,从事海量服务后台设计与研发工作,现在负责QQ群后台等项目,喜欢研究技术 ...
随机推荐
- 自定义GrildView实现单选功能
首先看实现功能截图,这是一个自定义Dialog,并且里面内容由GrildView 绑定数据源,实现类似单选功能. 首先自定义Dialog,绑定数据源 自定义Dialog弹出框大小方法 最主要实现的就是 ...
- 文本模板转换工具包和 ASP.NET MVC
http://msdn.microsoft.com/zh-sg/magazine/ee291528.aspx
- 慢牛系列四:好玩的React Native
在上次随笔(系列三)中,我试着用RN实现了一个Demo,感觉很不错,当时遇到的问题这篇文章里基本都解决了,比如导航动画问题,这篇文章里主要介绍RN的动画,学会动画以后,各种小创意都可以实现了^^ 下面 ...
- 在MacBook Air 上装Win10的,反反复复的失败过程。
这个月初,一个女性朋友托我帮她装电脑,往MacBook Air上面装Windows 系统,原因是windows用的习惯,用起来顺手.然后用脚趾头考虑了一下,就一口答应下来了.难道这就是一个标准程序员的 ...
- gulp初体验记录(简介、插件开发介绍)
目前用的业界比较知名的三个前端构建工具:grunt.gulp.fis,自己此前一直都是只在用grunt,fis看过一点,gulp则一直都没注意过,直到最近发现好像用的人越来越多,所以今天也就抽了点时间 ...
- onload是代码在也买你的追加元素的完成,而不是http请求的完成
- 《TCP/IP详解卷1:协议》第17、18章 TCP:传输控制协议(2)-读书笔记
章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...
- [设计模式] javascript 之 适配器模式
适配器模式说明 说明: 适配器模式,一般是为要使用的接口,不符本应用或本系统使用,而需引入的中间适配层类或对象的情况: 场景: 就好比我们买了台手机,买回来后发现,充电线插头是三插头,但家里,只有两插 ...
- Photoshop之渐变工具使用
最上面两个游标控制不透明度 下面两个控制渐变位置 点击游标可以设置颜色 基于每个游标进行操作
- C/C++语言算法题——替换
[问题] Description 给定一个有限长度的非负整数序列.一次操作是指从第一个元素开始,依次把数列中的每个数替换为它右边比它小的数的个数.对该数列不断进行这个操作.总有一个时刻该数列将不再发生 ...