422 lines
8.1 KiB
C++
422 lines
8.1 KiB
C++
//-------------------------------------------------------------------------------------------------------+
|
|
// Copyright (C), 1998-2007, SH Software Co. Ltd.
|
|
// = FileName : DualList 模板类
|
|
// = Version : ver2.0
|
|
// = Author : zjq
|
|
// = CreateDate : 2002-09-09
|
|
// = Description: DualList 声明 双向循环链表,提高了单向链表反向遍历和随机访问的速度
|
|
// = Maintainers:
|
|
//
|
|
//-------------------------------------------------------------------------------------------------------+
|
|
#ifndef _DUALLIST_H_
|
|
#define _DUALLIST_H_
|
|
|
|
#ifndef _LIST_H_
|
|
#include "List.h"
|
|
#endif
|
|
|
|
#ifndef _TABLE_H_
|
|
#include "Table.h"
|
|
#endif
|
|
|
|
#ifndef _DLISTNODE_H_
|
|
#include "DListNode.h"
|
|
#endif
|
|
|
|
template<class T> class DualList : public List< T >
|
|
{
|
|
public:
|
|
DualList(long initLength = 0);
|
|
DualList(const Table<T>& table);
|
|
DualList(const DualList<T>& table);
|
|
|
|
DualList<T>&operator =(const DualList<T>& table);
|
|
DualList<T>&operator =(const Table<T>& table);
|
|
|
|
virtual ~DualList();
|
|
|
|
virtual const T& GetAt(long index)const;
|
|
virtual const T* GetPre(const T* p)const;
|
|
|
|
virtual void MoveTo(long index);
|
|
virtual void MoveToPre();
|
|
|
|
virtual void InsertAfterCur(const T& t);
|
|
virtual void DelCur();
|
|
virtual void Clear();
|
|
|
|
virtual void DetachAfterCur();
|
|
virtual long Conbine(List<T>& list, long from = 0);
|
|
|
|
virtual void Arrange(bool bIncrease = true);
|
|
virtual void Arrange(int (*cmp)(const T&,const T&));
|
|
virtual void ReverseList();
|
|
virtual void Rotate(long iFrom, long iTo);
|
|
};
|
|
|
|
template<class T>
|
|
DualList<T>& DualList<T>::operator = (const DualList<T>& table)
|
|
{
|
|
this->DeepCopy(table);
|
|
return *this;
|
|
}
|
|
|
|
template<class T>
|
|
DualList<T>& DualList<T>::operator = (const Table<T>& table)
|
|
{
|
|
this->DeepCopy(table);
|
|
return *this;
|
|
}
|
|
|
|
template<class T>
|
|
void DualList<T>::Clear()
|
|
{
|
|
this->tail->next = NULL;
|
|
DListNode<T>*p = (DListNode<T>*)(this->head->next);
|
|
while(p != NULL)
|
|
{
|
|
DListNode<T> *pn = (DListNode<T>*)(p->next);
|
|
delete p;
|
|
p = pn;
|
|
}
|
|
this->curPos = this->tail = this->head->next = this->head;
|
|
((DListNode<T>*)this->head)->pre = this->head;
|
|
this->length = 0;
|
|
this->cur = -1;
|
|
}
|
|
|
|
template<class T>
|
|
const T* DualList<T>::GetPre(const T*p)const
|
|
{
|
|
return (p == NULL || p == ((const T*)(this->head->next))) ? NULL : (const T*)(((const DListNode<T>*)p)->pre);
|
|
}
|
|
|
|
template<class T>
|
|
const T& DualList<T>::GetAt(long index)const
|
|
{
|
|
ListNode<T>*p = this->curPos;
|
|
long i = this->cur;
|
|
for (; i < index; i++, p = p->next)
|
|
{
|
|
;
|
|
}
|
|
for (; i > index; i--, p = ((DListNode<T>*)p)->pre)
|
|
{
|
|
;
|
|
}
|
|
return p->data;
|
|
}
|
|
|
|
template<class T>
|
|
void DualList<T>::ReverseList()
|
|
{
|
|
if (this->length < 2)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ListNode<T>*p,*next = this->head->next,*pre = this->head;
|
|
for (long i = 0; i < this->length; i++)
|
|
{
|
|
p = next;
|
|
next = p->next;
|
|
p->next = pre;
|
|
((DListNode<T>*)pre)->pre = p;
|
|
pre = p;
|
|
}
|
|
|
|
p = this->head->next;
|
|
this->head->next = this->tail;
|
|
((DListNode<T>*)this->tail)->pre = this->head;
|
|
this->tail = p;
|
|
}
|
|
|
|
template<class T>
|
|
void DualList<T>::Arrange(bool bIncrease)
|
|
{
|
|
if (this->GetLength() < 2)
|
|
{
|
|
return;
|
|
}
|
|
if (bIncrease)
|
|
{
|
|
this->MoveToFirst();
|
|
this->MoveToNext();
|
|
while(!this->IsBegin())
|
|
{
|
|
T temp = this->GetCurData();
|
|
long i = this->GetCur();
|
|
ListNode<T>* pos = this->GetCurPos();
|
|
MoveToPre();
|
|
if (this->GetCurData() > temp)
|
|
{
|
|
while(!this->IsBegin() && this->GetCurData() > temp)
|
|
{
|
|
MoveToPre();
|
|
}
|
|
|
|
InsertAfterCur(temp);
|
|
this->curPos = pos;
|
|
this->cur = i + 1;
|
|
DelCur();
|
|
}
|
|
else
|
|
{
|
|
this->MoveToNext();
|
|
}
|
|
this->MoveToNext();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this->MoveToFirst();
|
|
this->MoveToNext();
|
|
while(!this->IsBegin())
|
|
{
|
|
T temp = this->GetCurData();
|
|
long i = this->GetCur();
|
|
ListNode<T>*pos = this->GetCurPos();
|
|
MoveToPre();
|
|
if (this->GetCurData() < temp)
|
|
{
|
|
while(!this->IsBegin() && this->GetCurData() < temp)
|
|
{
|
|
MoveToPre();
|
|
}
|
|
InsertAfterCur(temp);
|
|
this->curPos = pos;
|
|
this->cur = i + 1;
|
|
DelCur();
|
|
}
|
|
else
|
|
{
|
|
this->MoveToNext();
|
|
}
|
|
this->MoveToNext();
|
|
}
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
void DualList<T>::Arrange(int (*cmp)(const T&,const T&))
|
|
{
|
|
if (this->GetLength() < 2)
|
|
{
|
|
return;
|
|
}
|
|
this->MoveToFirst();
|
|
this->MoveToNext();
|
|
while(!this->IsBegin())
|
|
{
|
|
T temp = this->GetCurData();
|
|
long i = this->GetCur();
|
|
ListNode<T>* pos = this->GetCurPos();
|
|
MoveToPre();
|
|
if (cmp(this->GetCurData(),temp) > 0)
|
|
{
|
|
while(!this->IsBegin() && cmp(this->GetCurData(),temp) > 0)
|
|
{
|
|
MoveToPre();
|
|
}
|
|
InsertAfterCur(temp);
|
|
this->curPos = pos;
|
|
this->cur = i + 1;
|
|
DelCur();
|
|
}
|
|
else
|
|
{
|
|
this->MoveToNext();
|
|
}
|
|
this->MoveToNext();
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
void DualList<T>::InsertAfterCur(const T& t)
|
|
{
|
|
DListNode<T>* p = new DListNode<T>;
|
|
p->data = t;
|
|
p->next = this->curPos->next;
|
|
this->curPos->next = p;
|
|
p->pre = this->curPos;
|
|
((DListNode<T>*)(p->next))->pre = p;
|
|
this->length++;
|
|
this->cur++;
|
|
if (this->curPos == this->tail)
|
|
{
|
|
this->tail = p;
|
|
}
|
|
this->curPos = p;
|
|
}
|
|
|
|
template<class T>
|
|
void DualList<T>::DelCur()
|
|
{
|
|
DListNode<T>* p = (DListNode<T>*)this->curPos;
|
|
MoveToPre();
|
|
this->curPos->next = p->next;
|
|
((DListNode<T>*)(p->next))->pre = this->curPos;
|
|
if (p == this->tail)
|
|
{
|
|
this->tail = this->curPos;
|
|
}
|
|
delete p;
|
|
this->length--;
|
|
}
|
|
|
|
template<class T>
|
|
DualList<T>::DualList(long initLength)
|
|
{
|
|
delete this->head;
|
|
this->head = this->tail = new DListNode<T>;
|
|
this->head->next = this->head;
|
|
((DListNode<T>*)this->head)->pre = this->head;
|
|
this->curPos = this->head;
|
|
this->Realloc(initLength);
|
|
}
|
|
|
|
template<class T>
|
|
DualList<T>::DualList(const Table<T>&table)
|
|
{
|
|
delete this->head;
|
|
this->head = this->tail = new DListNode<T>;
|
|
this->head->next = this->head;
|
|
((DListNode<T>*)this->head)->pre = this->head;
|
|
this->curPos = this->head;
|
|
this->DeepCopy(table);
|
|
}
|
|
|
|
template<class T>
|
|
DualList<T>::DualList(const DualList<T>&table)
|
|
{
|
|
delete this->head;
|
|
this->head = this->tail = new DListNode<T>;
|
|
this->head->next = this->head;
|
|
((DListNode<T>*)this->head)->pre = this->head;
|
|
this->curPos = this->head;
|
|
this->DeepCopy(table);
|
|
}
|
|
|
|
template<class T>
|
|
DualList<T>::~DualList()
|
|
{
|
|
if (this->head == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Clear();
|
|
|
|
DListNode<T>* p = (DListNode<T>*)this->head;
|
|
delete p;
|
|
this->head = NULL;
|
|
}
|
|
|
|
template<class T>
|
|
void DualList<T>::MoveToPre()
|
|
{
|
|
this->curPos = ((DListNode<T>*)this->curPos)->pre;
|
|
this->cur--;
|
|
if (this->curPos == this->tail)
|
|
{
|
|
this->cur = this->length - 1;
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
void DualList<T>::MoveTo(long index)
|
|
{
|
|
if (this->IsValidIndex(index))
|
|
{
|
|
if (index == 0)
|
|
{
|
|
this->curPos = this->head->next;
|
|
this->cur = 0;
|
|
}
|
|
else if (index == this->GetLastIndex())
|
|
{
|
|
this->curPos = this->tail;
|
|
this->cur = index;
|
|
}
|
|
else if (index >= this->cur)
|
|
{
|
|
while(this->GetCur() != index)
|
|
{
|
|
this->MoveToNext();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while(this->GetCur() != index)
|
|
{
|
|
MoveToPre();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this->cur = -1;
|
|
this->curPos = this->head;
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
long DualList<T>::Conbine(List<T>&list,long from)
|
|
{
|
|
if (list.IsValidIndex(from))
|
|
{
|
|
ListNode<T>*first, *last;
|
|
list.MoveTo(from);
|
|
first = list.GetCurPos();
|
|
list.MoveToLast();
|
|
last = list.GetCurPos();
|
|
this->length += list.GetLength() - from;
|
|
list.DetachAfter(from - 1);
|
|
this->tail->next = first;
|
|
((DListNode<T>*)first)->pre = this->tail;
|
|
this->tail = last;
|
|
this->tail->next = this->head;
|
|
((DListNode<T>*)this->head)->pre = this->tail;
|
|
}
|
|
return this->length;
|
|
}
|
|
|
|
template<class T>
|
|
void DualList<T>::Rotate(long iFrom,long iTo)
|
|
{
|
|
if (iFrom != iTo)
|
|
{
|
|
long iNewZero = (iFrom - iTo + this->GetLength()) % this->GetLength();
|
|
MoveTo(iNewZero - 1 + this->GetLength() % this->GetLength());
|
|
ListNode<T>* newTail = this->GetCurPos();
|
|
MoveTo(iNewZero);
|
|
|
|
//形成环路
|
|
this->tail->next = this->head->next;
|
|
((DListNode<T>*)this->head->next)->pre = this->tail;
|
|
|
|
//更新head
|
|
this->head->next = this->curPos;
|
|
((DListNode<T>*)this->curPos)->pre = this->head;
|
|
this->cur = 0;
|
|
|
|
//更新tail
|
|
this->tail = newTail;
|
|
this->tail->next = this->head;
|
|
((DListNode<T>*)this->head)->pre = this->tail;
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
void DualList<T>::DetachAfterCur()
|
|
{
|
|
this->curPos->next = this->head;
|
|
((DListNode<T>*)this->head)->pre = this->curPos;
|
|
this->tail = this->curPos;
|
|
this->length = this->cur + 1;
|
|
}
|
|
|
|
|
|
#endif
|
|
|