//-------------------------------------------------------------------------------------------------------+ // 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 DualList : public List< T > { public: DualList(long initLength = 0); DualList(const Table& table); DualList(const DualList& table); DualList&operator =(const DualList& table); DualList&operator =(const Table& 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& 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 DualList& DualList::operator = (const DualList& table) { this->DeepCopy(table); return *this; } template DualList& DualList::operator = (const Table& table) { this->DeepCopy(table); return *this; } template void DualList::Clear() { this->tail->next = NULL; DListNode*p = (DListNode*)(this->head->next); while(p != NULL) { DListNode *pn = (DListNode*)(p->next); delete p; p = pn; } this->curPos = this->tail = this->head->next = this->head; ((DListNode*)this->head)->pre = this->head; this->length = 0; this->cur = -1; } template const T* DualList::GetPre(const T*p)const { return (p == NULL || p == ((const T*)(this->head->next))) ? NULL : (const T*)(((const DListNode*)p)->pre); } template const T& DualList::GetAt(long index)const { ListNode*p = this->curPos; long i = this->cur; for (; i < index; i++, p = p->next) { ; } for (; i > index; i--, p = ((DListNode*)p)->pre) { ; } return p->data; } template void DualList::ReverseList() { if (this->length < 2) { return; } ListNode*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*)pre)->pre = p; pre = p; } p = this->head->next; this->head->next = this->tail; ((DListNode*)this->tail)->pre = this->head; this->tail = p; } template void DualList::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* 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*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 void DualList::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* 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 void DualList::InsertAfterCur(const T& t) { DListNode* p = new DListNode; p->data = t; p->next = this->curPos->next; this->curPos->next = p; p->pre = this->curPos; ((DListNode*)(p->next))->pre = p; this->length++; this->cur++; if (this->curPos == this->tail) { this->tail = p; } this->curPos = p; } template void DualList::DelCur() { DListNode* p = (DListNode*)this->curPos; MoveToPre(); this->curPos->next = p->next; ((DListNode*)(p->next))->pre = this->curPos; if (p == this->tail) { this->tail = this->curPos; } delete p; this->length--; } template DualList::DualList(long initLength) { delete this->head; this->head = this->tail = new DListNode; this->head->next = this->head; ((DListNode*)this->head)->pre = this->head; this->curPos = this->head; this->Realloc(initLength); } template DualList::DualList(const Table&table) { delete this->head; this->head = this->tail = new DListNode; this->head->next = this->head; ((DListNode*)this->head)->pre = this->head; this->curPos = this->head; this->DeepCopy(table); } template DualList::DualList(const DualList&table) { delete this->head; this->head = this->tail = new DListNode; this->head->next = this->head; ((DListNode*)this->head)->pre = this->head; this->curPos = this->head; this->DeepCopy(table); } template DualList::~DualList() { if (this->head == NULL) { return; } Clear(); DListNode* p = (DListNode*)this->head; delete p; this->head = NULL; } template void DualList::MoveToPre() { this->curPos = ((DListNode*)this->curPos)->pre; this->cur--; if (this->curPos == this->tail) { this->cur = this->length - 1; } } template void DualList::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 long DualList::Conbine(List&list,long from) { if (list.IsValidIndex(from)) { ListNode*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*)first)->pre = this->tail; this->tail = last; this->tail->next = this->head; ((DListNode*)this->head)->pre = this->tail; } return this->length; } template void DualList::Rotate(long iFrom,long iTo) { if (iFrom != iTo) { long iNewZero = (iFrom - iTo + this->GetLength()) % this->GetLength(); MoveTo(iNewZero - 1 + this->GetLength() % this->GetLength()); ListNode* newTail = this->GetCurPos(); MoveTo(iNewZero); //形成环路 this->tail->next = this->head->next; ((DListNode*)this->head->next)->pre = this->tail; //更新head this->head->next = this->curPos; ((DListNode*)this->curPos)->pre = this->head; this->cur = 0; //更新tail this->tail = newTail; this->tail->next = this->head; ((DListNode*)this->head)->pre = this->tail; } } template void DualList::DetachAfterCur() { this->curPos->next = this->head; ((DListNode*)this->head)->pre = this->curPos; this->tail = this->curPos; this->length = this->cur + 1; } #endif