/*!
\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;
}