//-------------------------------------------------------------------------------------------------------+ // Copyright (C), 1998-2007, SH Software Co. Ltd. // = FileName : SPTable 模板类 // = Version : ver2.0 // = Author : zjq // = CreateDate : 2002-09-09 // = Description: SPTable 声明 动态指针数据,外部分配内存,内部释放,也可外部释放,支持空数据 // 适用于大型数据类,用于减小动态分配空间和数据复制开销,同时保持较高的数据访问速度。 // = Maintainers: // //-------------------------------------------------------------------------------------------------------+ #ifndef _SPTABLE_H_ #define _SPTABLE_H_ #ifndef _SQTABLE_H_ #include "SqTable.h" #endif templateclass SPTable : public SqTable { public: SPTable(long size = 0,long unit = 10); virtual ~SPTable(); virtual void Realloc(long newLength); //bCopy = false 将释放所有数据空间! virtual void SetLength(long newLength,bool bCopy = true); virtual bool Move(long from,long to); virtual void DelCur(); virtual void Clear(); virtual void ReleaseCur(); //取走数据,清空指针,但不删除指针表项! virtual T* FetchCur(); //attribute long GetDataNum() const; bool IsCurEmpty() const; bool IsEmptyData(long i) const; bool operator == (const SPTable&table) const; bool operator != (const SPTable&table) const; T& GetCurPData(); T& operator ()(long i); const T& GetPData(long i) const; //在第一个空数据处填入新数据,返回索引,move cur long FillIn(T*p); void Release(long i); //释放数据空间,清空所有指针 void ReleaseAll(); T* Fetch(long i); T* FetchFirst(); T* FetchLast(); long FindAndDel(T* t); long FindDataOrAddTail(const T& t); 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; //二分查找,适用于升序表 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); //稳定计数排序, 不支持空数据!但速度快。 virtual void Arrange(bool bIncrease = true); //稳定计数排序。 virtual void Arrange(int (*cmp)(const T&,const T&)); //稳定计数排序,空数据将排列在最后 void ArrangeEx(bool bIncrease = true); }; template SPTable::SPTable(long size,long unit):SqTable(size,unit) { } template bool SPTable::operator != (const SPTable&table) const { return !(*this == table); } template T& SPTable::GetCurPData() { return *this->GetCurData(); } template T& SPTable::operator ()(long i) { return *((*this)[i]); } template const T& SPTable::GetPData(long i) const { return *this->GetAt(i); } template void SPTable::Release(long i) { this->MoveTo(i); ReleaseCur(); } template T* SPTable::Fetch(long i) { this->MoveTo(i); return FetchCur(); } template T* SPTable::FetchFirst() { this->MoveToFirst(); return FetchCur(); } template T* SPTable::FetchLast() { this->MoveToLast(); return FetchCur(); } template long SPTable::FindDataOrAddTail(const T&t) { long pos = FindData(t); if (pos == NOT_FOUND) { T*p = new T; *p = t; return this->AddTail(p); } else { return pos; } } template void SPTable::FindDataOrInsertHead(const T&t) { long pos = FindData(t); if (pos == NOT_FOUND) { T*p = new T; *p = t; this->InsertHead(p); } } template long SPTable::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 SPTable::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 SPTable::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 long SPTable::FindAndDel(T*t) { //只可能有一个t指针 long i = this->Find(t); if (i != NOT_FOUND) { this->Del(i); return 1; } return 0; } template long SPTable::FillIn(T*p) { long i(0); for (i = 0;!IsEmptyData(i);i++); {//可能是末尾增加 (*this)[i] = p; } return i; } template bool SPTable::operator == (const SPTable&table) const { if (table.GetLength() != this->GetLength()) { return false; } for (long i = 0;iGetLength();i++) { if (this->GetAt(i) != NULL && table.GetAt(i) != NULL) { if (!(*(this->GetAt(i)) == *(table.GetAt(i)))) { return false; } } else if (!(this->GetAt(i) == NULL && table.GetAt(i) == NULL)) { return false; } } return true; } template SPTable::~SPTable() { ReleaseAll(); } template void SPTable::ReleaseAll() { for (this->MoveToFirst();!this->IsOut();this->MoveToNext()) { ReleaseCur(); } } template void SPTable::Clear() { ReleaseAll(); SqTable::Clear(); } template bool SPTable::IsCurEmpty() const { return this->IsOut() ? true : this->GetAt(this->GetCur()) == NULL; } template bool SPTable::IsEmptyData(long i) const { return this->IsValidIndex(i) ? this->GetAt(i) == NULL : true; } template void SPTable::ReleaseCur() { if (IsCurEmpty()) { return; } delete this->GetCurData(); this->SetCurData(NULL); } template void SPTable::DelCur() { ReleaseCur(); long last = this->GetLastIndex(); if (this->GetCur() < last) {//至少两项、且非最后项 //保存、清零最后项,否则将被SqTable::DelCur() delete! T* pLast = this->pData[last]; this->pData[last] = NULL; SqTable::DelCur(); //重新推入最后项 this->pData[last-1] = pLast; } else { SqTable::DelCur(); } } template T* SPTable::FetchCur() { if (this->IsOut()) { return NULL; } T*p = this->GetCurData(); this->SetCurData(NULL); return p; } template void SPTable::Realloc(long newLength) { if (newLength>this->GetLength()) { long oldLength = this->GetLength(); SqTable::Realloc(newLength); for (long i = oldLength;ipData[i] = NULL; } } else if (newLengthGetLength()) { for (long i = newLength;iGetLength();i++) { if (this->pData[i] != NULL) { delete this->pData[i]; } } SqTable::Realloc(newLength); } } template void SPTable::SetLength(long newLength,bool bCopy) { if (bCopy) { if (newLength>this->GetLength()) { long oldLength = this->GetLength(); SqTable::SetLength(newLength,true); for (long i = oldLength;ipData[i] = NULL; } } else if (newLengthGetLength()) { for (long i = newLength;iGetLength();i++) { if (this->pData[i] != NULL) { delete this->pData[i]; } } SqTable::SetLength(newLength,true); } } else { ReleaseAll(); SqTable::SetLength(newLength,false); } } template bool SPTable::Move(long from,long to) { if (from == to || from == to-1) { return false; } this->MoveTo(from); T* p = this->GetCurData(); this->SetCurData(NULL); this->Insert(to,p); 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 long SPTable::FindData(const T&t,long from,long to) const { if (to < 0 || to >= this->GetLength()) { to = this->GetLastIndex(); } for (long i = from;i <= to;i++) { if (this->pData[i] != NULL && *(this->pData[i]) == t) { return i; } } return NOT_FOUND; } template long SPTable::FindData(const T&t,Quene&quene,long from,long to) const { if (to < 0 || to >= this->GetLength()) { to = this->GetLastIndex(); } for (long i = from;i <= to;i++) { if (this->pData[i] != NULL && *(this->pData[i]) == t) { quene.EnQuene(i); } } return quene.GetLength(); } template long SPTable::FindDataAndDel(const T&t) { long count = 0; for (this->MoveToFirst();!this->IsOut();this->MoveToNext()) { if (*this->GetCurData() == t) { DelCur(); count++; } } return count; } template long SPTable::GetDataNum() const { long count = 0; for (long i = 0;iGetLength();i++) { if (this->pData[i] != NULL) { count++; } } return count; } template void SPTable::Arrange(bool bIncrease) { if (this->GetLength()<2) { return; } long *count = new long[this->GetLength()]; long i; for (i = 0;iGetLength();i++) { count[i] = i; } if (bIncrease) { for (i = 0; i < this->GetLastIndex();i++) { for (long j = i + 1; j < this->GetLength(); j++) { if (*(this->pData[i]) > *(this->pData[j])) { count[i]++; count[j]--; } } } for (i = 0;iGetLength();i++) { if (count[i] != i) { long k,j; T *temp1 = this->pData[i],*temp2; k = count[i]; while(k != i) { temp2 = this->pData[k]; this->pData[k] = temp1; temp1 = temp2; j = k; k = count[j]; count[j] = j; } this->pData[i] = temp1; count[i] = i; } } } else { for (i = 0;iGetLastIndex();i++) { for (long j = i+1; j < this->GetLength(); j++) { if (*(this->pData[i]) < *(this->pData[j])) { count[i]++; count[j]--; } } } for (i = 0;iGetLength();i++) { if (count[i] != i) { long k,j; T *temp1 = this->pData[i],*temp2; k = count[i]; while(k != i) { temp2 = this->pData[k]; this->pData[k] = temp1; temp1 = temp2; j = k; k = count[j]; count[j] = j; } this->pData[i] = temp1; count[i] = i; } } } delete[] count; } template void SPTable::Arrange(int (*cmp)(const T&,const T&)) { if (this->GetLength() < 2) { return; } long *count = new long[this->GetLength()]; long i; for (i = 0;iGetLength();i++) { count[i] = i; } for (i = 0;iGetLastIndex();i++) { for (long j = i+1;jGetLength();j++) { if (cmp(*(this->pData[i]),*(this->pData[j]))>0) { count[i]++; count[j]--; } } } for (i = 0;iGetLength();i++) { if (count[i] != i) { long k,j; T *temp1 = this->pData[i],*temp2; k = count[i]; while(k != i) { temp2 = this->pData[k]; this->pData[k] = temp1; temp1 = temp2; j = k; k = count[j]; count[j] = j; } this->pData[i] = temp1; count[i] = i; } } delete[] count; } template void SPTable::ArrangeEx(bool bIncrease) { if (this->GetLength() < 2) { return; } long *count = new long[this->GetLength()]; long i; for (i = 0;iGetLength();i++) { count[i] = i; } if (bIncrease) { for (i = 0;iGetLastIndex();i++) { for (long j = i+1;jGetLength();j++) { if (this->pData[j] != NULL && (this->pData[i] == NULL || *(this->pData[i]) > *(this->pData[j]))) { count[i]++; count[j]--; } } } for (i = 0;iGetLength();i++) { if (count[i] != i) { long k,j; T *temp1 = this->pData[i],*temp2; k = count[i]; while(k != i) { temp2 = this->pData[k]; this->pData[k] = temp1; temp1 = temp2; j = k; k = count[j]; count[j] = j; } this->pData[i] = temp1; count[i] = i; } } } else { for (i = 0;iGetLastIndex();i++) { for (long j = i+1;jGetLength();j++) { if (this->pData[j] != NULL && (this->pData[i] == NULL || *(this->pData[i]) < *(this->pData[j]))) { count[i]++; count[j]--; } } } for (i = 0;iGetLength();i++) { if (count[i] != i) { long k,j; T *temp1 = this->pData[i],*temp2; k = count[i]; while(k != i) { temp2 = this->pData[k]; this->pData[k] = temp1; temp1 = temp2; j = k; k = count[j]; count[j] = j; } this->pData[i] = temp1; count[i] = i; } } } delete[] count; } #endif