zoukankan      html  css  js  c++  java
  • 练习系列 4、异质链表

    /*!
    \file List.h
    \author 刘宝
    \version 1.0
    \date 2010/12/3
    \brief 异质链表List及其节点接口IListNode的声明
    */
     
    #ifndef LIST
    #define LIST
     
    class IListNode;
    class List;
    class ListPrivate;
     
    /*! List中iterate遍历函数使用的回调函数 */
    typedef bool (*callback)(IListNode *, int index, void * param);
     
    /*!
    \class IListNode
    \brief List链表使用的节点接口类
    */
    class IListNode
    {
        /*! 声明List为友元,便于List访问process函数和私有指针 */
        friend class List;
     
    public:
        IListNode(): owner(0), prev(0), next(0) {}
        IListNode(const IListNode &node): owner(0), prev(0), next(0) {}
        IListNode &operator=(const IListNode &node);
        virtual ~IListNode(); //! 析构函数
     
    protected:
        /*!
        protected类型纯虚处理函数,子类实现后用于处理相应子类
        \param param 处理函数参数,将由List::processAll(void *param) const传入
        \return 若处理成功返回true,否则返回false
        */
        virtual bool process(void *param) = 0;
     
    private:
        List *owner;
        IListNode *prev;
        IListNode *next;
    };
     
    /*!
    \class List
    \brief 异质链表类,使用继承自IListNode的节点,无法被复制
    本异质链表类具有以下特点:
    - 支持基本的插入、删除、遍历、清空等操作
    - processAll遍历链表中的各异质节点,依次执行其process操作
    - iterate能够使用自定义回调函数遍历链表中的各异质节点
    - 插入删除节点更安全,拷贝节点也更安全:
        - 已经在链表中的节点无法再次被插入到任何链表中
        - 只能删除当前链表中的节点
        - 节点间相互拷贝不会影响链表
        - 在Debug模式下,节点先于链表删除会产生断言失败
    - 本链表无法被复制(确保链表不会被意外破坏)
    */
    class List
    {
    public:
        /*! insert操作插入位置枚举 */
        enum Position
        {
            Head,   /*!< 链表首部 */
            Tail    /*!< 链表尾部 */
        };
     
        List();
        ~List();
     
        /*!
        在pos位置插入node节点
        \param pos 插入位置,见Position
        \param node 待插入节点的指针
        \return 插入成功返回true,否则返回false
        */
        bool insert(Position pos, IListNode *node);
     
        /*!
        在第index-1节点后插入node节点
        \param index 插入位置,插入后该节点将处于index位置
        \param node 待插入节点的指针
        \return 插入成功返回true,否则返回false
        */
        bool insertAt(int index, IListNode *node);
     
        /*!
        从链表中删除node节点
        \param node 待删除节点的指针
        \return 删除成功返回true,否则返回false
        */
        bool remove(IListNode *node);
     
        /*!
        从链表中删除第index个节点
        \param index 待删除节点的索引
        \return 插入成功返回true,否则返回false
        */
        bool removeAt(int index);
     
        /*!
        使用func回调函数遍历链表,param参数将传入回调函数中
        \param func 回调函数指针
        \param param 回调函数参数
        \return 若遍历的func回调函数全部返回true,返回true,否则返回false
        */
        bool iterate(callback func, void *param);
     
        /*!
        遍历链表,并调用每个节点的process函数
        \param param 传入每个节点process函数的参数
        \return 若每个节点的process都返回true,返回true,否则返回false
        */
        bool processAll(void *param) const;
     
        /*!
        清空链表,但不释放节点
        \return 成功返回true,否则返回false
        */
        bool clear();
     
        /*!
        判断链表中是否存在节点node
        \param node 待检测是否被包含在链表中的节点的指针
        \return 链表中存在node返回true,否则返回false
        */
        bool contains(const IListNode *node) const;
     
        /*!
        判断链表是否为空
        \return 若链表空返回true,否则返回false
        */
        bool isEmpty() const;
     
        /*!
        获得链表中节点个数
        \return 链表中节点个数
        */
        int count() const;
     
        /*!
        获得链表中位于index处的节点的指针
        \param index 索引位置
        \return 位于index处的节点的指针
        */
        IListNode * at(int index) const;
     
    public:
        /*!
        静态函数,用来处理节点(调用节点的process函数)
        \param node 待处理节点的指针
        \param param 传入node的process函数的参数
        \return node的process返回值
        */
        static bool process(IListNode *node, void *param);
     
    private:
        ListPrivate *list;
        IListNode *head;
        IListNode *tail;
     
    private:
        List(const List &list);//! 禁用拷贝构造函数
        List &operator=(const List &list);//! 禁用赋值构造函数
     
    private:
        bool isolate(IListNode *node) const;
        bool prepare(IListNode *node) const;
        bool hasNode(const IListNode *node) const;
        bool noOwner(const IListNode *node) const;
     
    private:
        static bool isolateCallback(IListNode *node, int index, void *param);
    };
     
    #endif
    /*!
    \file List.cpp
    \author 刘宝
    \version 1.0
    \date 2010/12/3
    \brief 异质链表List及其节点接口IListNode的实现
    */
     
    #include <assert.h>
    #include <stddef.h>
    #include "List.h"
     
    class ListPrivate
    {
    public:
        ListPrivate() : _count(0) {}
     
        inline void incCount() {++_count;}
        inline void decCount() {--_count;}
        inline void rstCount() {_count = 0;}
        inline int count() const {return _count;}
     
        inline bool isValidIndex(int index)
        {
            return (index >= 0 && index < _count) ?
                true : false;
        }
     
    private:
        int _count;
    };
     
     
    IListNode &IListNode::operator=(const IListNode &node)
    {
        /*! 阻断指针复制 */
        return *this;
    }
     
    IListNode::~IListNode()
    {
        /*!
            当IListNode还在List中时就销毁会触发此处断言。
            请先从List中删除该节点再销毁该节点!
        */
        assert(!owner && !prev && !next);
    }
     
    List::List() : list(new ListPrivate), head(0), tail(0)
    {
     
    }
     
    List::~List()
    {
        (void)clear();
    }
     
    bool List::insert(Position pos, IListNode *node)
    {
        bool retVal = false;
     
        if((pos == Head || pos == Tail) && prepare(node))
        {
            if(!head && !tail)//空链表时
                head = tail = node;
            else
            {
                assert(head && tail);
     
                /*
                    此时链表中应当至少存在一个节点,
                    并且head和tail应当都不为NULL。
                */
     
                switch(pos)
                {
                case Head://插入到头部
                    head->prev = node;
                    node->next = head;
                    head = node;
                    break;
                case Tail://插入到尾部
                    tail->next = node;
                    node->prev = tail;
                    tail = node;
                    break;
                default://不应该发生
                    assert(0);
                }
            }
     
            list->incCount();//增加count计数
            retVal = true;
        }
     
        return retVal;
    }
     
    bool List::insertAt(int index, IListNode *node)
    {
        bool retVal = false;
     
        if(index == 0)
            retVal = insert(Head, node);//相当于在头部插入node
        else if(index == list->count())
            retVal = insert(Tail, node);//相当于在尾部插入node
        else
        {
            assert(head && tail);
     
            /* 在第index-1个节点后插入node */
            IListNode *prevNode = at(index - 1);
     
            if(prevNode && prepare(node))
            {
                node->next = prevNode->next;
                node->prev = prevNode;
     
                assert(prevNode->next);//prevNode的next不应当为NULL
     
                prevNode->next->prev = node;
                prevNode->next = node;
     
                list->incCount();//增加count计数
                retVal = true;
            }
        }
     
        return retVal;
    }
     
    bool List::remove(IListNode *node)
    {
        bool retVal = false;
     
        if(hasNode(node))
        {
            if(head == node)
                head = node->next;
            if(tail == node)
                tail = node->prev;
     
            /* 修改node前后节点的相关指针 */
            if(node->next)
                node->next->prev = node->prev;
            if(node->prev)
                node->prev->next = node->next;
     
            /* 孤立该节点 */
            (void)isolate(node);
     
            list->decCount();//减少count计数
            retVal = true;
        }
     
        return retVal;
    }
     
    bool List::removeAt(int index)
    {
        return remove(at(index));
    }
     
    bool List::iterate(callback func, void *param)
    {
        bool retVal = false;
     
        if(func && head && tail)
        {
            IListNode *iterator = head;
     
            {
                IListNode *tempPtr = NULL;
                int index = 0;
     
                /*
                    使用tempPtr缓存iterator->next指针是为了
                    使本函数能够遍历过程中删除节点。
                */
                do
                    tempPtr = iterator->next;   //缓存iterator->next指针到tempPtr
                while(func(iterator, index++, param) && (iterator = tempPtr));
            }
     
            /* 遍历成功完成 */
            if(!iterator) retVal = true;
        }
     
        return retVal;
    }
     
    bool List::clear()
    {
        bool retVal = false;
     
        if(list->count() && (retVal = iterate(isolateCallback, this)))
        {
            list->rstCount();   /* 把计数器置0 */
            head = 0;
            tail = 0;
        }
     
        return retVal;
    }
     
    bool List::processAll(void *param) const
    {
        bool retVal = false;
     
        if(head && tail)
        {
            IListNode *iterator = head;
     
            /* 从head遍历全部,并执行process函数 */
            while(iterator->process(param) && (iterator = iterator->next));
     
            /* 遍历成功完成 */
            if(!iterator) retVal = true;
        }
     
        return retVal;
    }
     
    bool List::contains(const IListNode *node) const
    {
        return hasNode(node);
    }
     
    bool List::isEmpty() const
    {
        return !list->count();
    }
     
    int List::count() const
    {
        return list->count();
    }
     
    IListNode *List::at(int index) const
    {
        IListNode *retVal = NULL;
     
        /* 如果index有效 */
        if(list->isValidIndex(index))
        {
            IListNode *iterator = head;
     
            /* 从head开始寻找第index个节点 */
            for(;index && (iterator = iterator->next); --index);
     
            /* 遍历成功完成 */
            if(!index) retVal = iterator;
        }
     
        return retVal;
    }
     
    bool List::process(IListNode *node, void *param)
    {
        return node ? node->process(param) : false;
    }
     
    bool List::isolate(IListNode *node) const
    {
        if(hasNode(node))
        {
            node->owner = NULL;
            node->prev = NULL;
            node->next = NULL;
     
            return true;
        }
        else
            return false;
    }
     
    bool List::prepare(IListNode *node) const
    {
        if(noOwner(node))
        {
            node->owner = const_cast<List *>(this);
            node->prev = NULL;
            node->next = NULL;
     
            return true;
        }
        else
            return false;
    }
     
    bool List::hasNode(const IListNode *node) const
    {
        return node ? node->owner == this : false;
    }
     
    bool List::noOwner(const IListNode *node) const
    {
        return node ? !node->owner : false;
    }
     
    bool List::isolateCallback(IListNode *node, int index, void *param)
    {
        List *self = (List *)param;
     
        return self ? self->isolate(node) : false;
    }
    #include <iostream>
    #include <assert.h>
    #include "List.h"
     
    using namespace std;
     
    class SquareNode : public IListNode
    {
    public:
        SquareNode(int length) : x(length) {}
     
    protected:
        bool process(void *param)
        {
            return cout << x * x << endl;
        }
     
    private:
        int x;
    };
     
    class RoundNode : public IListNode
    {
    public:
        RoundNode(int radius) : r(radius) {}
     
    protected:
        bool process(void *param)
        {
            return cout << 3.14 * r * r << endl;
        }
     
    private:
        int r;
    };
     
    class RectangleNode : public IListNode
    {
    public:
        RectangleNode(int length, int width) : x(length), y(width) {}
     
    protected:
        bool process(void *param)
        {
            return cout << x * y << endl;
        }
     
    private:
        int x;
        int y;
    };
     
    bool ListNodeProcessor(IListNode *node, int index, void *param)
    {
        cout << index << "->";
        return List::process(node, param);
    }
     
    void TestList()
    {
        SquareNode square1(5), square2(7);
        RoundNode round1(4), round2(6);
        RectangleNode rect1(3, 7), rect2(4, 8);
        List list;
     
        assert(list.insert(List::Head, &square1));
        assert(!list.insert(List::Head, &square1)); /*!< 重复插入链表内节点会失败 */
        assert(list.remove(&square1));
        assert(!list.processAll(NULL));             /*!< 对空链表遍历会失败 */
        assert(list.insert(List::Head, &square1));  /*!< 从链表移出的节点可以再次插入 */
        assert(list.insert(List::Tail, &round2));
        assert(list.processAll(NULL));
        assert(list.remove(&round2));
        assert(list.processAll(NULL));
        assert(list.insert(List::Head, &round2));
        assert(list.remove(&round2));
        assert(list.processAll(NULL));
        assert(!list.insertAt(-1, &round1));
        assert(!list.insertAt(list.count() + 1, &round1));
        assert(list.insertAt(1, &round1));
        assert(list.insertAt(1, &round2));
        assert(list.count() == 3);
        assert(list.processAll(NULL));
        for(int i = 0; i < list.count(); ++i)
            assert(List::process(list.at(i), NULL));
        assert(list.iterate(ListNodeProcessor, NULL));
        assert(!list.removeAt(-1));
        assert(!list.removeAt(list.count()));
        assert(list.removeAt(0));
        assert(list.count() == 2);
        assert(list.removeAt(list.count() - 1));
        assert(list.count() == 1);
        assert(!list.isEmpty());
        assert(list.clear());
        assert(list.isEmpty());
    }
     
    int main()
    {
        TestList();
    //    SquareNode node(1);
    //    SquareNode copyNode1 = node;
    //    SquareNode copyNode2(node);
    //    SquareNode assignNode(2);
    //    assignNode = node;
    //    cout << "testCopy:" << endl;
    //
    //    SquareNode testNode(66);
    //    List list;
    //    assert(list.insertAt(0, &node));
    //    node = testNode;
        return 0;
    }
  • 相关阅读:
    无废话WPF系列9: Binding的源
    无废话WPF系列7:WPF布局控件
    无废话WPF系列6:各类控件家族详解
    无废话WPF系列13:路由事件
    无废话WPF系列4: x名称空间
    无废话WPF系列12: 依赖属性和附加属性
    用C++设计一个不能被继承的类
    HMM的介绍及实现
    C语言综合实验3—计算器四则运算
    机器学习基础
  • 原文地址:https://www.cnblogs.com/codingmylife/p/1989035.html
Copyright © 2011-2022 走看看