691 lines
11 KiB
C++
691 lines
11 KiB
C++
//-------------------------------------------------------------------------------------------------------+
|
|
// Copyright (C), 1998-2007, SH Software Co. Ltd.
|
|
// = FileName : DList 模板类
|
|
// = Version : ver2.0
|
|
// = Author : zjq
|
|
// = CreateDate : 2002-09-09
|
|
// = Description: DList 声明 双向链表
|
|
// = Maintainers:
|
|
//
|
|
//-------------------------------------------------------------------------------------------------------+
|
|
#ifndef _DLIST_H_
|
|
#define _DLIST_H_
|
|
|
|
#ifndef _NODE_H_
|
|
#include "Node.h"
|
|
#endif
|
|
|
|
template <class R>
|
|
class DList
|
|
{
|
|
public:
|
|
DList(int dFlag = 1);
|
|
// 用数组初始化链表, 不能用于字符串数组!!
|
|
DList(R * addr, int nCount);
|
|
~DList();
|
|
|
|
int operator !() const;
|
|
// 移到当前指针到第 n 个节点, 并返回它所指的值
|
|
R * operator [](int n);
|
|
const R & operator [](int n) const;
|
|
|
|
void MoveToHead();
|
|
|
|
const R & GetAt(int n) const;
|
|
R * GetAt(int n);
|
|
|
|
//并入
|
|
DList<R>& operator << (DList<R>&listother);
|
|
|
|
//复制
|
|
DList<R>& copyFrom(const DList<R>& listother);
|
|
|
|
void Insert(R * node);
|
|
void Append(R * node);
|
|
void Replace(R * node, int n = -1);
|
|
void Reset();
|
|
|
|
int Remove();
|
|
int Remove(int n);
|
|
|
|
// 求当前指针的位置(-1: current 为 NULL)
|
|
int CurPosition() const;
|
|
|
|
int Length() const;
|
|
|
|
int GetDelFlag() const;
|
|
void SetDelFlag(int nFlag);
|
|
|
|
R * CurData() const;
|
|
void SetCurData(R* p);
|
|
|
|
int Find(const R * node);
|
|
int Exist(const R * node) const;
|
|
|
|
// 把指针移到最后,准备下一个插入
|
|
void MoveEnd();
|
|
|
|
R* Head() const;
|
|
R* Tail() const;
|
|
R* FindNode(const void *, int (*cmp)(const R *, const void *));
|
|
|
|
void QuickSort(int (*cmp)(const R *, const R *));
|
|
void Swap(int n1,int n2);
|
|
void Reverse();
|
|
void FindAndDel(const void *p, int (*cmp)(const R *, const void *));
|
|
|
|
private:
|
|
int m_nLen, m_nCurIndex;
|
|
Node<R>* m_pCurrent;
|
|
|
|
protected:
|
|
int m_nDelFlag;
|
|
Node<R>* head;
|
|
Node<R>* tail;
|
|
|
|
virtual int Compare(const R *, const R *) const;
|
|
|
|
private:
|
|
DList<R> & operator = (const DList<R> &src);
|
|
DList(const DList<R> &src);
|
|
|
|
};
|
|
|
|
template <class R>
|
|
DList<R>::DList(const DList<R> &src)
|
|
{
|
|
m_nDelFlag = src.m_nDelFlag;
|
|
for (int i = 0;i < src.Length();i++)
|
|
{
|
|
Append(new R( src[i] ) );
|
|
}
|
|
}
|
|
|
|
template <class R>
|
|
inline DList<R>::DList(int nFlag)
|
|
{
|
|
head = tail = m_pCurrent = NULL;
|
|
m_nDelFlag = nFlag;
|
|
m_nCurIndex = 0;
|
|
m_nLen = 0;
|
|
}
|
|
|
|
template <class R>
|
|
DList<R>::DList( R *pBeg, int nCount) : head(NULL), tail(NULL), m_pCurrent(NULL), m_nDelFlag(1), m_nCurIndex(0), m_nLen(0)
|
|
{
|
|
R *p = pBeg;
|
|
for (int i = 0; i < nCount; i++)
|
|
{
|
|
Append(new R(*p));
|
|
p++;
|
|
}
|
|
}
|
|
|
|
template <class R>
|
|
DList<R>::~DList()
|
|
{
|
|
Node<R> *p = head, *p1 = NULL;
|
|
while(p)
|
|
{
|
|
p1 = p->next;
|
|
if (m_nDelFlag)
|
|
{
|
|
if (p->data != NULL)
|
|
{
|
|
delete p->data;
|
|
}
|
|
}
|
|
delete p;
|
|
p = p1;
|
|
}
|
|
}
|
|
|
|
template <class R>
|
|
inline void DList<R>::Append(R * node)
|
|
{
|
|
m_pCurrent = NULL;
|
|
m_nCurIndex = m_nLen;
|
|
Insert(node);
|
|
}
|
|
|
|
template <class R>
|
|
inline void DList<R>::Replace(R * node, int n)
|
|
{
|
|
if (n >= 0)
|
|
{
|
|
(*this)[n];
|
|
}
|
|
|
|
if (m_pCurrent)
|
|
{
|
|
if (m_nDelFlag)
|
|
{
|
|
if (m_pCurrent->data != NULL)
|
|
{
|
|
delete m_pCurrent->data;
|
|
}
|
|
}
|
|
m_pCurrent->data = node;
|
|
}
|
|
}
|
|
|
|
template <class R>
|
|
inline int DList<R>::Remove(int n)
|
|
{
|
|
(*this)[n];
|
|
return Remove();
|
|
}
|
|
|
|
template <class R>
|
|
inline int DList<R>::CurPosition() const
|
|
{
|
|
return m_nCurIndex<m_nLen ? m_nCurIndex : -1;
|
|
}
|
|
|
|
template <class R>
|
|
inline int DList<R>::Length() const
|
|
{
|
|
return m_nLen;
|
|
}
|
|
|
|
template <class R>
|
|
inline void DList<R>::SetDelFlag(int nFlag)
|
|
{
|
|
m_nDelFlag = nFlag;
|
|
}
|
|
|
|
template <class R>
|
|
inline int DList<R>::GetDelFlag() const
|
|
{
|
|
return m_nDelFlag;
|
|
}
|
|
|
|
template <class R>
|
|
inline int DList<R>::operator !() const
|
|
{
|
|
if (head)
|
|
{
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
template <class R>
|
|
inline const R & DList<R>::operator [](int n) const
|
|
{
|
|
DList<R> *pThis = (DList<R> *)this;
|
|
const R * pData = (*pThis)[n];
|
|
return *pData;
|
|
}
|
|
|
|
template <class R>
|
|
inline void DList<R>::MoveToHead()
|
|
{
|
|
m_pCurrent = head;
|
|
m_nCurIndex = 0;
|
|
}
|
|
|
|
// 移到当前指针到第 n 个节点, 并返回它
|
|
// 假如 n<0, exit; ||则移到倒数第 n个节点
|
|
template <class R>
|
|
inline R * DList<R>::operator [](int n)
|
|
{
|
|
int i = 0;
|
|
if (n >= 0 && n < m_nLen)
|
|
{
|
|
if (!m_pCurrent)
|
|
{
|
|
m_pCurrent=head;
|
|
m_nCurIndex=0;
|
|
}
|
|
|
|
int diff = n - m_nCurIndex;
|
|
if (diff >= 0)
|
|
{
|
|
if (m_nCurIndex == 0 && n == m_nLen - 1)
|
|
{
|
|
m_pCurrent=tail;
|
|
m_nCurIndex=m_nLen - 1;
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < diff; i++)
|
|
{
|
|
assert(m_pCurrent != NULL);
|
|
m_pCurrent = m_pCurrent->next;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (m_nCurIndex == m_nLen - 1 && n == 0)
|
|
{
|
|
m_pCurrent=head;
|
|
m_nCurIndex=0;
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < -diff; i++)
|
|
{
|
|
assert(m_pCurrent != NULL);
|
|
m_pCurrent = m_pCurrent->previous;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
assert(0);
|
|
}
|
|
m_nCurIndex = n;
|
|
|
|
if (m_pCurrent)
|
|
{
|
|
return m_pCurrent->data;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
template <class R>
|
|
inline const R & DList<R>::GetAt(int n) const
|
|
{
|
|
DList<R> *pThis = (DList<R> *)this;
|
|
const R * pData = (*pThis).GetAt(n);
|
|
return *pData;
|
|
}
|
|
|
|
// 移到当前指针到第 n 个节点, 并返回它
|
|
// 假如 n<0, exit; ||则移到倒数第 n个节点
|
|
template <class R>
|
|
inline R * DList<R>::GetAt(int n)
|
|
{
|
|
int i = 0;
|
|
if (n >= 0 && n < m_nLen)
|
|
{
|
|
if (!m_pCurrent)
|
|
{
|
|
m_pCurrent=head;
|
|
m_nCurIndex=0;
|
|
}
|
|
|
|
int diff = n - m_nCurIndex;
|
|
if (diff >= 0)
|
|
{
|
|
for (i = 0; i < diff; i++)
|
|
{
|
|
assert(m_pCurrent != NULL);
|
|
m_pCurrent = m_pCurrent->next;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (m_nCurIndex == m_nLen - 1 && n == 0)
|
|
{
|
|
m_pCurrent=head;
|
|
m_nCurIndex=0;
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < -diff; i++)
|
|
{
|
|
assert(m_pCurrent != NULL);
|
|
m_pCurrent = m_pCurrent->previous;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
assert(0);
|
|
}
|
|
m_nCurIndex = n;
|
|
|
|
if (m_pCurrent)
|
|
{
|
|
return m_pCurrent->data;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
template <class R>
|
|
inline R * DList<R>::CurData() const
|
|
{
|
|
return m_pCurrent ? m_pCurrent->data : NULL;
|
|
}
|
|
|
|
template <class R>
|
|
inline void DList<R>::SetCurData(R* p)
|
|
{
|
|
if (m_pCurrent != NULL)
|
|
{
|
|
m_pCurrent->data = p;
|
|
}
|
|
}
|
|
|
|
template <class R>
|
|
inline void DList<R>::MoveEnd()
|
|
{
|
|
m_nCurIndex = -1;
|
|
m_pCurrent = NULL;
|
|
}
|
|
|
|
template <class R>
|
|
inline R* DList<R>::Head() const
|
|
{
|
|
if (head)
|
|
{
|
|
return head->data;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
template <class R>
|
|
inline R* DList<R>::Tail() const
|
|
{
|
|
if (tail)
|
|
{
|
|
return tail->data;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
template <class R>
|
|
inline void DList<R>::FindAndDel(const void *p, int (*cmp)(const R *, const void *))
|
|
{
|
|
while(FindNode(p,cmp) != NULL)
|
|
{
|
|
Remove();
|
|
}
|
|
}
|
|
|
|
//并入链表,list被直接连接到this链表的末尾,成为this链表的一部分
|
|
//最后this链表的游标值不变,而list变为Reset状态
|
|
template <class R>
|
|
DList<R>& DList<R>::operator << (DList<R> &listother)
|
|
{
|
|
if (listother.Length() == 0)
|
|
{
|
|
return *this;
|
|
}
|
|
|
|
if (Length() > 0)
|
|
{
|
|
tail->next = listother.head;
|
|
listother.head->previous = tail;
|
|
}
|
|
else
|
|
{
|
|
head = listother.head;
|
|
}
|
|
|
|
//new tail
|
|
tail = listother.tail;
|
|
|
|
//increase length
|
|
m_nLen += listother.Length();
|
|
|
|
//reset list
|
|
listother.head = listother.tail = listother.m_pCurrent = NULL;
|
|
listother.m_nLen = listother.m_nCurIndex = 0;
|
|
|
|
return *this;
|
|
}
|
|
|
|
template <class R>
|
|
DList<R>& DList<R>::copyFrom(const DList<R>& listother)
|
|
{
|
|
m_nDelFlag = listother.m_nDelFlag;
|
|
if (this != &listother)
|
|
{
|
|
Reset();
|
|
for (int i = 0;i < listother.Length();i++)
|
|
{
|
|
Append(new R( listother[i] ) );
|
|
}
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
template <class R>
|
|
inline DList<R> & DList<R>::operator = (const DList<R> &src)
|
|
{
|
|
return copyFrom(src);
|
|
}
|
|
|
|
|
|
// 重新初始化
|
|
template <class R>
|
|
void DList<R>::Reset()
|
|
{
|
|
Node<R> *p = head, *p1 = NULL;
|
|
while(p)
|
|
{
|
|
p1 = p->next;
|
|
if (m_nDelFlag)
|
|
{
|
|
if (p->data != NULL)
|
|
{
|
|
delete p->data;
|
|
}
|
|
}
|
|
delete p;
|
|
p = p1;
|
|
}
|
|
head = tail = m_pCurrent = NULL;
|
|
m_nLen = 0; m_nCurIndex = 0;
|
|
}
|
|
|
|
template <class R>
|
|
int DList<R>::Exist(const R * node) const
|
|
{
|
|
for (Node<R> *p = head; p != NULL; p = p->next)
|
|
{
|
|
if (Compare(p->data, node) == 0)
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
template <class R>
|
|
int DList<R>::Find(const R * node)
|
|
{
|
|
for (m_nCurIndex = 0; m_nCurIndex < m_nLen; m_nCurIndex++)
|
|
{
|
|
if (Compare((*this)[m_nCurIndex], node) == 0)
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
template <class R>
|
|
inline int DList<R>::Compare(const R * node1, const R *node2) const
|
|
{
|
|
if (node1 == node2)
|
|
{
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
// 删除当前节点
|
|
template <class R>
|
|
int DList<R>::Remove()
|
|
{
|
|
if (!m_pCurrent)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
Node<R> *p, *n;
|
|
p = m_pCurrent->previous;
|
|
n = m_pCurrent->next;
|
|
if (m_pCurrent == head)
|
|
{ //删除头节点
|
|
if (m_nDelFlag)
|
|
{
|
|
if (m_pCurrent->data != NULL)
|
|
{
|
|
delete m_pCurrent->data;
|
|
}
|
|
}
|
|
delete m_pCurrent;
|
|
head = m_pCurrent = n;
|
|
if (!n)
|
|
{
|
|
tail = NULL;
|
|
}
|
|
if (n)
|
|
{
|
|
n->previous = NULL;
|
|
}
|
|
}
|
|
else if (p)
|
|
{ // 当前节点变为下一个节点
|
|
if (m_nDelFlag)
|
|
{
|
|
if (m_pCurrent->data != NULL)
|
|
{
|
|
delete m_pCurrent->data;
|
|
}
|
|
}
|
|
delete m_pCurrent;
|
|
p->next = n;
|
|
if (n)
|
|
{
|
|
n->previous = p;
|
|
}
|
|
else
|
|
{
|
|
tail = p; //删除尾节点
|
|
}
|
|
m_pCurrent = n;
|
|
}
|
|
else
|
|
{
|
|
assert(0);
|
|
}
|
|
m_nLen--;
|
|
return 1;
|
|
}
|
|
|
|
// 在当前节点之前增加
|
|
template <class R>
|
|
void DList<R>::Insert( R *dat)
|
|
{
|
|
assert(dat != NULL);
|
|
|
|
if (head == NULL)
|
|
{
|
|
head = tail = new Node<R> (NULL, NULL, dat);
|
|
assert(head != NULL);
|
|
m_pCurrent = NULL; //缺省插入尾部
|
|
}
|
|
else if (m_pCurrent == NULL)
|
|
{ //加到尾部
|
|
Node<R> *tmp =new Node<R> (tail, NULL, dat);
|
|
assert(tmp != NULL);
|
|
tail->next = tmp;
|
|
tail = tmp;
|
|
}
|
|
else if (m_pCurrent->previous)
|
|
{ //插入中间
|
|
Node<R> *p = m_pCurrent->previous;
|
|
p->next = m_pCurrent->previous = new Node<R> (p,m_pCurrent,dat);
|
|
assert(p->next != NULL);
|
|
}
|
|
else if (m_pCurrent == head)
|
|
{ // 加到表头前 curren == head
|
|
head = new Node<R> (NULL, m_pCurrent, dat);
|
|
assert(head != NULL);
|
|
m_pCurrent->previous = head;
|
|
}
|
|
m_nLen++;
|
|
m_nCurIndex++;
|
|
}
|
|
|
|
template <class R>
|
|
void DList<R>::QuickSort(int (*cmp)(const R *, const R *))
|
|
{
|
|
int len = Length(), nsr = -1;
|
|
for (int i = 0; i < len - 1; i++)
|
|
{
|
|
for (int j = 0; j < len - 1 - i; j++)
|
|
{
|
|
R *s1 = (*this)[j];
|
|
Node<R> *n1 = m_pCurrent;
|
|
R *s2 = (*this)[j + 1];
|
|
Node<R> *n2 = m_pCurrent;
|
|
|
|
nsr = cmp(s1, s2);
|
|
if (nsr > 0)
|
|
{
|
|
R *tmp = s1;
|
|
n1->data = s2;
|
|
n2->data = tmp;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 可以用关键字查找链表中的某一项, 因此用 void *
|
|
template <class R>
|
|
R * DList<R>::FindNode(const void *target, int (*cmp)(const R *, const void *))
|
|
{
|
|
int len = Length(), nsr = -1;
|
|
for (int i = 0; i < len; i++)
|
|
{
|
|
R *s1 = (*this)[i];
|
|
nsr = cmp(s1, target);
|
|
if (!nsr)
|
|
{
|
|
return s1;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
template <class R>
|
|
void DList<R>::Swap(int n1,int n2)
|
|
{
|
|
if ((n1 >= 0 && n1 < m_nLen) && ( n2 >= 0 && n2 < m_nLen))
|
|
{
|
|
R* swap1=(*this)[n1];
|
|
Node<R> *node1 = m_pCurrent;
|
|
R* swap2 = (*this)[n2];
|
|
Node<R> *node2 = m_pCurrent;
|
|
R *temp = swap1;
|
|
|
|
node1->data = swap2;
|
|
node2->data = temp;
|
|
}
|
|
else
|
|
{
|
|
assert(NULL);
|
|
}
|
|
}
|
|
|
|
template <class R>
|
|
void DList<R>::Reverse()
|
|
{
|
|
CPtrArray arPtrs;
|
|
int i = 0;
|
|
for (i = 0; i < m_nLen; i++)
|
|
{
|
|
arPtrs.Add((*this)[i]);
|
|
}
|
|
|
|
for (i = 0; i < m_nLen; i++)
|
|
{
|
|
(*this)[i];
|
|
m_pCurrent->data = (R*)arPtrs.GetAt(m_nLen - i - 1);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|