//-------------------------------------------------------------------------------------------------------+ // Copyright (C), 1998-2007, SH Software Co. Ltd. // = FileName : PDList 模板类 // = Version : ver2.0 // = Author : zjq // = CreateDate : 2002-09-09 // = Description: PDList 声明 双向指针链表,内存外部分配,自动释放,也提供外部释放接口。支持空指针。 // 适用于大型数据对象,随机访问较少,空间动态分配经常发生的情况。 // = Maintainers: // //-------------------------------------------------------------------------------------------------------+ #ifndef _PDLIST_H_ #define _PDLIST_H_ #ifndef _DUALLIST_H_ #include "DualList.h" #endif templateclass PDList:public DualList { public: PDList(long size = 0); virtual ~PDList(); virtual void DelCur(); virtual void Clear(); //索引以未移动时为准 virtual bool Move(long from,long to); //稳定插入排序,空数据将排列在最后 virtual void Arrange(bool bIncrease = true); //稳定插入排序 virtual void Arrange(int (*cmp)(const T&,const T&)); //attribute bool operator == (const PDList&list) const; bool operator != (const PDList&list) const; //返回已经分配空间、实际存在的数据数目, <= this->GetLength(). long GetDataNum() const; bool IsCurEmpty() const; bool IsEmptyData(long index) const; //direct data access T &GetCurPData(); const T& GetPData(long i) const; T &operator()(long index); //fetch //取走数据,并删除结点 T* FetchCur(); T* Fetch(long i); T* FetchFirst(); T* FetchLast(); //release //仅释放数据空间,不删除指针空间,不改变链表长度,不移动cur; void ReleaseCur(); void Release(long i); void ReleaseAll(); long FillIn(T*t); //search //仅仅为了速度而替换Table long FindAndDel(T*t); //没发现,加到最后,并返回index; long FindDataOrAddTail(const T&t); //没发现插入Head void FindDataOrInsertHead(const T&t); long FindDataAndDel(const T&t); long FindData(const T&t,long from = 0,long to = -1) const; long FindData(const T&t,Quene&quene,long from = 0,long to = -1) const; //sort //二分查找,适用于升序表 long BFindData(const T&t,long from = 0,long to = -1) const; //二分查找,并移动游标,适用于升序表 bool BFindDataTo(const T&t,long from = 0,long to = -1); //构造升序表,如返回false,外部释放p bool SortIn(T*p,bool bAllowDup = false); protected: virtual void Realloc(long newLength); }; template bool PDList::operator != (const PDList&list) const { return !((*this) == list); } template bool PDList::IsCurEmpty() const { return this->IsOut() ? true : this->curPos->data == NULL; } template T& PDList::GetCurPData() { return *this->GetCurData(); } template const T& PDList::GetPData(long i) const { return *this->GetAt(i); } template T& PDList::operator()(long index) { return *((*this)[index]); } template void PDList::Release(long i) { this->MoveTo(i); ReleaseCur(); } template T* PDList::Fetch(long i) { this->MoveTo(i); return FetchCur(); } template T* PDList::FetchFirst() { this->MoveToFirst(); return FetchCur(); } template T* PDList::FetchLast() { this->MoveToLast(); return FetchCur(); } template long PDList::BFindData(const T&t,long from,long to) const { if (to < 0 || to >= this->GetLength()) { to = this->GetLastIndex(); } if (from > to) { return NOT_FOUND; } if (t < GetPData(from)) { return NOT_FOUND; } if (t > GetPData(to)) { return NOT_FOUND; } while(from <= to) { long mid = (from+to)/2; const T& tCur = GetPData(mid); if (t > tCur) { from = mid+1; } else if (t < tCur) { to = mid-1; } else { return mid; } } return NOT_FOUND; } template bool PDList::BFindDataTo(const T&t,long from,long to) { if (to < 0 || to >= this->GetLength()) { to = this->GetLastIndex(); } if (this->IsEmpty()) { this->MoveTo(0); return false; } this->MoveTo(from); if (t < GetCurPData()) { return false; } this->MoveTo(to); if (t > GetCurPData()) { this->MoveToNext(); return false; } while(from < to) { long mid = (from+to)/2; this->MoveTo(mid); const T& tCur = GetCurPData(); if (t > tCur) { from = mid+1; } else if (t < tCur) { to = mid-1; } else { return true; } } if (from == to) { this->MoveTo(from); const T& tCur = GetCurPData(); if (t > tCur) { this->MoveToNext(); } else if (!(t < tCur)) { return true; } return false; } return false; } template bool PDList::SortIn(T*p,bool bAllowDup) { if (BFindDataTo(*p)) { if (!bAllowDup) { return false; } //需要找最后一个 this->MoveToNext(); while(!this->IsOut() && GetCurPData() == *p) { this->MoveToNext(); } } this->InsertCur(p); return true; } template void PDList::Clear() { this->tail->next = NULL; DListNode*p = (DListNode*)(this->head->next); while(p != NULL) { DListNode *pn = (DListNode*)(p->next); if (p->data != NULL) { delete p->data; } 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 PDList::PDList(long size) { //作为遍历结束条件 this->head->data = NULL; if (size > 0) {//未用基类的构造函数来调用Realloc(size)!!!,因为那时子类还未创建 Realloc(size); } } template long PDList::FindAndDel(T*t) { for (this->MoveToFirst();!this->IsOut();this->MoveToNext()) { if (this->GetCurData() == t) { DelCur(); return 1; } } return 0; } template long PDList::FillIn(T*t) { for (this->MoveToFirst();!IsCurEmpty();this->MoveToNext()); if (this->IsOut()) { this->AddTail(t); } else { this->SetCurData(t); } return this->GetCur(); } template void PDList::ReleaseAll() { for (this->MoveToFirst();!this->IsOut();this->MoveToNext()) { ReleaseCur(); } } template bool PDList::operator == (const PDList&list) const { if (list.GetLength() != this->GetLength()) { return false; } T* const*pCur0,*const*pCur1; for (pCur0 = this->GetFirst(),pCur1 = list.GetFirst();pCur0 != NULL; pCur0 = this->GetNext(pCur0), pCur1 = list.GetNext(pCur1)) { if (*pCur0 != NULL && *pCur1 != NULL && **pCur0 != **pCur1) { return false; } else if (!(*pCur0 == NULL && *pCur1 == NULL)) { return false; } } return true; } template T* PDList::FetchCur() { if (this->IsOut()) { return NULL; } T* p = this->GetCurData(); this->SetCurData(NULL); DelCur(); return p; } template void PDList::Realloc(long newLength) { if (newLength>this->GetLength()) { long oldCur = this->cur; ListNode*oldPos = this->curPos; while(this->GetLength()AddTail(NULL); } this->curPos = oldPos; this->cur = oldCur; } } template PDList::~PDList() { if (this->head == NULL) { return; } ReleaseAll(); } template long PDList::GetDataNum() const { long count = 0; T* const*pCur = this->GetFirst(); for (long i = 0;iGetLength();i++,pCur = this->GetNext(pCur)) { if (*pCur != NULL) { count++; } } return count; } template bool PDList::IsEmptyData(long index) const { return this->IsValidIndex(index)?this->GetAt(index) == NULL:true; } template void PDList::ReleaseCur() { if (IsCurEmpty()) { return; } delete this->GetCurData(); this->SetCurData(NULL); } template void PDList::DelCur() { if (this->GetCurData() != NULL) { delete this->GetCurData(); } DualList::DelCur(); } template long PDList::FindDataOrAddTail(const T&t) { long pos = FindData(t,0,this->GetLastIndex()); if (pos == NOT_FOUND) { T*p = new T; *p = t; return this->AddTail(p); } else { return pos; } } template void PDList::FindDataOrInsertHead(const T&t) { long pos = FindData(t,0,this->GetLastIndex()); if (pos == NOT_FOUND) { T*p = new T; *p = t; this->InsertHead(p); } } template long PDList::FindDataAndDel(const T&t) { long count = 0; for (this->MoveToFirst();!this->IsOut();this->MoveToNext()) { if (this->GetCurData() != NULL && *(this->GetCurData()) == t) { DelCur(); count++; } } return count; } template long PDList::FindData(const T&t,long from,long to) const { if (to < 0 || to >= this->GetLength()) { to = this->GetLastIndex(); } T* const* pCur = NULL; long i; for (pCur = this->GetTo(from),i = from;i <= to;pCur = this->GetNext(pCur),i++) { if (*pCur != NULL && **pCur == t) { return i; } } return NOT_FOUND; } template long PDList::FindData(const T&t,Quene&quene,long from,long to) const { if (to < 0 || to >= this->GetLength()) { to = this->GetLastIndex(); } T*const* pCur = NULL; long i; for (pCur = this->GetTo(from),i = from;i <= to;pCur = this->GetNext(pCur),i++) { if (*pCur != NULL && **pCur == t) { return quene.EnQuene(i); } } return quene.GetLength(); } template bool PDList::Move(long from,long to) { if (from == to || from == to-1) { return false; } this->MoveTo(from); T* t = this->GetCurData(); this->SetCurData(NULL); this->Insert(to,t); if (from > to) { this->Del(from+1);//from数据已经后移 this->MoveTo(to);//to是最终位置 } else { this->Del(from); this->MoveTo(to-1);//to-1是最终位置 } return true; } template void PDList::Arrange(bool bIncrease) { if (this->GetLength() < 2) { return; } long nullCount = 0; if (bIncrease) { this->MoveToFirst(); while(IsCurEmpty()) { this->DelFirst(); nullCount++; this->MoveToFirst(); } this->MoveToNext(); while(!this->IsBegin()) { if (!IsCurEmpty()) { T *temp = this->GetCurData(); long i = this->GetCur(); ListNode*pos = this->GetCurPos(); this->MoveToPre(); if (*this->GetCurData() > *temp) { while(!this->IsBegin() && *this->GetCurData() > *temp) { this->MoveToPre(); } this->InsertAfterCur(temp); this->curPos = pos; this->cur = i+1; this->SetCurData(NULL); DelCur(); } else { this->MoveToNext(); } } else { DelCur(); nullCount++; } this->MoveToNext(); } } else { this->MoveToFirst(); while(IsCurEmpty()) { this->DelFirst(); nullCount++; this->MoveToFirst(); } this->MoveToNext(); while(!this->IsBegin()) { if (!IsCurEmpty()) { T *temp = this->GetCurData(); long i = this->GetCur(); ListNode*pos = this->GetCurPos(); this->MoveToPre(); if (*this->GetCurData() < *temp) { while(!this->IsBegin() && *this->GetCurData() < *temp) { this->MoveToPre(); } this->InsertAfterCur(temp); this->curPos = pos; this->cur = i+1; this->SetCurData(NULL); DelCur(); } else { this->MoveToNext(); } } else { DelCur(); nullCount++; } this->MoveToNext(); } } while(nullCount-- != NULL) { this->AddTail(NULL); } } template void PDList::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(); this->MoveToPre(); if (cmp(*this->GetCurData(),*temp) > 0) { while(!this->IsBegin() && cmp(*this->GetCurData(),*temp) > 0) { this->MoveToPre(); } this->InsertAfterCur(temp); this->curPos = pos; this->cur = i+1; this->SetCurData(NULL); DelCur(); } else { this->MoveToNext(); } this->MoveToNext(); } } #endif