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;
        }
    }

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

  1. Redis list实现原理 - 双向循环链表

    双向链表 双向表示每个节点知道自己的直接前驱和直接后继,每个节点需要三个域 查找方向可以是从左往右也可以是从右往左,但是要实现从右往左还需要终端节点的地址,所以通常会设计成双向的循环链表; 双向的循环 ...

  2. Dancing Links 模板

    struct dl{ // x: line, y: column struct node{ int c, left, right, up, down; }; vector<node> a; ...

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

    本文是通过例子学习C++的第七篇,通过这个例子可以快速入门c++相关的语法. 1.问题描述 回顾一下约瑟夫环问题:n 个人围坐在一个圆桌周围,现在从第 s 个人开始报数,数到第 m 个人,让他出局:然 ...

  4. 侯捷STL学习(一)

    开始跟着<STL源码剖析>的作者侯捷真人视频,学习STL,了解STL背后的真实故事! 视频链接:侯捷STL 还有很大其他视频需要的留言 第一节:STL版本和重要资源 STL和标准库的区别 ...

  5. 侯捷STL课程及源码剖析学习1

    1.C++标准库和STL C++标准库以header files形式呈现: C++标准库的header files不带后缀名(.h),例如#include <vector> 新式C hea ...

  6. 侯捷STL学习(一)--顺序容器测试

    开始跟着<STL源码剖析>的作者侯捷真人视频,学习STL,了解STL背后的真实故事! 视频链接:侯捷STL 还有很大其他视频需要的留言 第一节:STL版本和重要资源 STL和标准库的区别 ...

  7. 详解DLX及其应用

    什么是DLX? 让我们看看百度百科上的解释:在 计算机科学 中, Dancing Links ,舞蹈链, 也叫 DLX, 是由 Donald Knuth 提出的数据结构,目的是快速实现他的 X算法.X ...

  8. Josephus环类问题,java实现

    写出一个双向的循环链表,弄一个计数器,我定义的是到三的时候,自动删除当前节点,很简单. package Com; import java.util.Scanner; /* * 约瑟夫环问题,有n个人组 ...

  9. Redis入门指南(第2版) Redis设计思路学习与总结

    https://www.qcloud.com/community/article/222 宋增宽,腾讯工程师,16年毕业加入腾讯,从事海量服务后台设计与研发工作,现在负责QQ群后台等项目,喜欢研究技术 ...

随机推荐

  1. Java 的 JSON 开源类库选择比较(zz)

    在看了作者的介绍,然后我又到mvnrepository上去看了各个库的的使用数之后,发现只能在jackson和gson之间做选择. 以下是原文 有效选择七个关于Java的JSON开源类库 April  ...

  2. [CareerCup] 12.5 Test a Pen 测试一支笔

    12.5 How would you testa pen? 这道题让我们测试一支笔,我们需要问面试官许多问题来理解"who,what,where,when,how and why" ...

  3. 实验二实验报告 20135324&&20135330

    北京电子科技学院(BESTI) 实 验 报 告 课程: 深入理解计算机系统 班级: 1353 姓名: 杨舒雯 张若嘉 学号: 20135324 20135330 成绩: 指导教师: 娄嘉鹏 实验日期: ...

  4. 5332盛照宗 如何获取新技能+c语言学习调查

    如何获取新技能+c语言学习调查 你有什么技能比大多人(超过90%以上)更好? 如果问我有没有什么技能比大多数人,并且是90%的人好,我还真不敢说有,因为世界上有70亿人,要比63亿人做的好才行啊.我也 ...

  5. WIN8 浏览器排版不兼容问题

    经常访问网站失败 访问部分网站只显示白底蓝字没有排版也没有图片 尝试了网上的各种方法,也是用了360和百度安全管家的网页修复 重置了IE设置 都不行!!! 最后有效的方法是 更换DNS 208.67. ...

  6. 人家为撩妹就鼓捣个网页,我做了个约炮APP(已开源)

    每年初夏第一场雷雨刚过,漫步河边的草坪,总是能闻到伴随着泥土的清新,这不是coco的前香,让人神魂颠倒:也不是gucci的后香,让人痴迷如梦.如24节气一样,它提醒人们,夏天到了.昨晚成都下了第一场雷 ...

  7. flatbuffers 使用问题记录

    1. 命名空间的问题 ----------------------------- namespace 1.0.3 版本包含文件类型前面不需要加命名空间,但是1.1.0 中包含需要在类型前加命名空间 i ...

  8. VS2010版快捷键

    VS2010版快捷键 Ctrl+E,D ----格式化全部代码 Ctrl+E,F ----格式化选中的代码 CTRL + SHIFT + B生成解决方案 CTRL + F7 生成编译 CTRL + O ...

  9. AngularJS开发指南6:AngularJS表单详解

    表单控件(input, select, textarea )是用来获取用户输入的.表单则是一组有联系的表单控件的集合. 用户能通过表单和表单控件提供验证的服务,知道自己的输入是否合法.这样能让用户交互 ...

  10. Ibatis学习总结4--SQL Map XML 映射文件扩展

    SQL Map XML 映射文件除了上文提到的属性还有一些其他重要的属性,下文将详细介绍这些属性. 缓存 Mapped Statement 结果集 通过在查询 statement 中指定 cacheM ...