C++ 模板双向不循环链表!!

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;

}

}

时间: 2024-10-13 12:26:48

C++ 模板双向不循环链表!!的相关文章

C语言实现双向非循环链表的逆序打印

我在上一篇博客中<C语言实现双向非循环链表>实现了如何构造一个双向非循环链表,并实现了正向打印.我还在之前一篇博客<C语言实现单链表的逆序打印>中实现了单链表的逆序打印.这篇博客我们来实现对双向非循环链表进行逆序打印,实现起来非常的简单.代码已经上传至 https://github.com/chenyufeng1991/ReverseDoubleLinkedList . 核心代码如下: //打印非循环双向链表,这个其实是正向打印 void printList(Node *pNode

C语言实现双向非循环链表的节点插入

我在之前一篇博客中<C语言实现双向非循环链表的逆序打印>讲到了如何逆序输出一个双向非循环链表,让我们对这种链表类型有了理性的认识.今天我们要来实现的是对双向非循环链表进行节点的插入.大家可以和<C语言实现单链表节点的插入>单链表的节点插入对比着学习.代码上传至  https://github.com/chenyufeng1991/InsertDoubleLinkedList . 核心代码如下: Node *InsertList(Node *pNode,int pos,int x){

C语言实现双向非循环链表(带头结点尾结点)的节点插入

对于双向链表,个人推荐使用带头结点尾结点的方式来处理会比较方便.我在<C语言实现双向非循环链表(不带头结点)的节点插入>中详细实现了在不带头结点的情况下的插入.这次我们将会来在使用头结点尾结点的情况下在任意的位置插入元素.代码上传至 https://github.com/chenyufeng1991/InsertNodeDoubleLinkedList_HeadNode . 核心代码如下: //插入一个节点 //插入位置分别为0,1,2,..... int InsertNodeList(Nod

C语言实现双向非循环链表的清空

我在之前一篇博客<C语言实现单链表的基本操作>实现了如何清空一个单链表,现在换成了双向的非循环链表,整体思路是一样的.代码上传至:https://github.com/chenyufeng1991/ClearDoubleLinkedList  . 核心代码如下: Node *ClearDoubleLinkedList(Node *pNode){ if (pNode == NULL) { printf("%s函数执行,原链表就是空链表,无须执行该方法\n",__FUNCTIO

双向不循环链表

下边程序实现的是一个双向不循环链表. #include <stdio.h> #include <stdlib.h> #include <string.h> #define new(p) ((p) = malloc(sizeof(*(p)))) #define IFNAMSIZ 16 struct interface *int_last, *int_list; struct interface { struct interface *next, *prev; char n

通过例子进阶学习C++(七)CMake项目通过模板库实现约瑟夫环

本文是通过例子学习C++的第七篇,通过这个例子可以快速入门c++相关的语法. 1.问题描述 回顾一下约瑟夫环问题:n 个人围坐在一个圆桌周围,现在从第 s 个人开始报数,数到第 m 个人,让他出局:然后从出局的下一个人重新开始报数,数到第 m 个人,再让他出局......,如此反复直到所有人全部出局为止. 上一篇我们通过数组.静态链表实现了约瑟夫环,具体参考: 通过例子进阶学习C++(六)你真的能写出约瑟夫环么 本文,我们进一步深入分析约瑟夫环问题,并通过c++模板库实现该问题求解,最后我们说明

数据结构之链表

---恢复内容开始--- 1:有头节点.单向.不循环链表 对于这种有头节点的单向不循环链表插入数据如下图: 1)头部插入 2)尾部插入 代码如下 : 1 #include "stdafx.h" 2 #include<iostream> 3 4 using namespace std; 5 6 typedef int DATA; 7 typedef struct node* LIST; 8 9 struct node 10 { 11 DATA data; 12 struct

Redis设计思路学习与总结

版权声明:本文由宋增宽原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/222 来源:腾云阁 https://www.qcloud.com/community 宋增宽,腾讯工程师,16年毕业加入腾讯,从事海量服务后台设计与研发工作,现在负责QQ群后台等项目,喜欢研究技术,并思考技术演变,专注于高并发业务架构的设计与性能优化. 下半年利用空余时间研究和分析了部分Redis源码,本文从网络模型.数据结构和内存管理.持久化和多机

Josephus环类问题,java实现

写出一个双向的循环链表,弄一个计数器,我定义的是到三的时候,自动删除当前节点,很简单. package Com; import java.util.Scanner; /* * 约瑟夫环问题,有n个人组成的圈,数到3的那个人出列,下个人继续从一开始 */ public class Josephus { public static void main(String[] args) { Scanner s = new Scanner(System.in); int n = Integer.parseI