练习系列 - 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;
}
posted @ 2011-03-19 20:19  紫红的泪  阅读(1868)  评论(0编辑  收藏  举报