Files
gjm 164968b62e chore
把非utf8-bom编码的cpp/h文件改为 utf8 bom 编码, msvc识别utf8编码时,如果不是bom格式的,会使用当前cp_oem来解码.
2026-10-04 00:04:20 +08:00

757 lines
12 KiB
C++

//-----------------------------------------------------------------------------+
// Copyright (C), 1998-2007, SH Software Co. Ltd.
// = FileName : XPDList 模板类
// = Version : ver2.0
// = Author : zjq
// = CreateDate : 2002-09-09
// = Description: XPDList 声明
// = Maintainers:
//
//-----------------------------------------------------------------------------+
#ifndef _XPDList_H_
#define _XPDList_H_
#ifndef _XDualList_H_
#include "XDualList.h"
#endif
#ifndef _QUENE_H_
#include "Quene.h"
#endif
//双向指针链表,内存外部分配,自动释放,也提供外部释放接口。支持空指针。
//适用于大型数据对象,随机访问较少,空间动态分配经常发生的情况。
template<class T>class XPDList : public XDualList<T*>
{
public:
XPDList(long size = 0,long groupMax = 25,long allocSize = 100);
virtual ~XPDList();
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&));
bool operator == (const XPDList<T>&list)const;
bool operator != (const XPDList<T>&list)const;
//返回已经分配空间、实际存在的数据数目,<=GetLength().
long GetDataNum()const;
bool IsCurEmpty()const;
bool IsEmptyData(long index)const;
//直接数据访问
//非空数据
T &GetCurPData();
//非空数据
const T& GetPData(long i)const;
//非空数据
T &operator()(long index);
//取走数据,并删除结点
T* FetchCur();
T* Fetch(long i);
T* FetchFirst();
T* FetchLast();
//仅释放数据空间,不删除指针空间,不改变链表长度,不移动cur;
void ReleaseCur();
void Release(long i);
void ReleaseAll();
long FillIn(T*t);
//search
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<long>&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);
protected:
virtual void Realloc(long newLength);
void SetAll(const T*p);//禁止操作
};
//二分查找
template<class T>
long XPDList<T>::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<class T>
bool XPDList<T>::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<class T>
bool XPDList<T>::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<class T>
void XPDList<T>::Clear()
{
this->group.Clear();
this->tail->next = NULL;
DListNode<T*>*p = (DListNode<T*>*)(this->head->next);
while(p != NULL)
{
DListNode<T*> *pn = (DListNode<T*>*)(p->next);
if (p->data != NULL)
{
delete p->data;
}
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>
XPDList<T>::XPDList(long size, long groupMax, long allocSize)
: XDualList<T*>(0,groupMax,allocSize)
{
this->head->data = NULL;//作为遍历结束条件
if (size > 0)
{
Realloc(size);//未用基类的构造函数来调用Realloc(size)!!!,因为那时子类还未创建
}
}
template<class T>
long XPDList<T>::FillIn(T*t)
{
for (this->MoveToFirst(); !IsCurEmpty(); this->MoveToNext());
{
if (this->IsOut())
{
this->AddTail(t);
}
else
{
this->SetCurData(t);
}
}
return this->GetCur();
}
template<class T>
void XPDList<T>::ReleaseAll()
{
for (this->MoveToFirst(); !this->IsOut(); this->MoveToNext())
{
ReleaseCur();
}
}
template<class T>
bool XPDList<T>::operator ==(const XPDList<T>&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<class T>
void XPDList<T>::Realloc(long newLength)
{
if (newLength > this->GetLength())
{
long oldCur = this->cur;
ListNode<T*>*oldPos = this->curPos;
while (this->GetLength() < newLength)
{
this->AddTail(NULL);
}
this->curPos = oldPos;
this->cur = oldCur;
}
}
template<class T>
XPDList<T>::~XPDList()
{
if (this->head == NULL)
{
return;
}
ReleaseAll();
}
template<class T>
long XPDList<T>::GetDataNum()const
{
long count = 0;
T* const*pCur = this->GetFirst();
for (long i = 0; i < this->GetLength(); i++, pCur = this->GetNext(pCur))
{
if (*pCur != NULL)
{
count++;
}
}
return count;
}
template<class T>
void XPDList<T>::DelCur()
{
if (this->GetCurData() != NULL)
{
delete this->GetCurData();
}
XDualList<T*>::DelCur();
}
template<class T>
long XPDList<T>::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<class T>
long XPDList<T>::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<class T>
long XPDList<T>::FindData(const T&t,Quene<long>&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<class T>
bool XPDList<T>::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<class T>
void XPDList<T>::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<T*>*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<T*>*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<class T>
void XPDList<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();
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();
}
}
template<class T>
bool XPDList<T>::operator != (const XPDList<T>&list)const
{
return !((*this) == list);
}
template<class T>
bool XPDList<T>::IsCurEmpty()const
{
return this->IsOut() ? true : this->curPos->data == NULL;
}
template<class T>
T &XPDList<T>::GetCurPData()
{
return *this->GetCurData();
}
template<class T>
const T& XPDList<T>::GetPData(long i)const
{
return *this->GetAt(i);
}
template<class T>
T &XPDList<T>::operator()(long index)
{
return *((*this)[index]);
}
template<class T>
T* XPDList<T>::Fetch(long i)
{
this->MoveTo(i);
return FetchCur();
}
template<class T>
T* XPDList<T>::FetchFirst()
{
this->MoveToFirst();
return FetchCur();
}
template<class T>
T* XPDList<T>::FetchLast()
{
this->MoveToLast();
return FetchCur();
}
template<class T>
void XPDList<T>::Release(long i)
{
this->MoveTo(i);
ReleaseCur();
}
template<class T>
long XPDList<T>::FindAndDel(T*t)
{
for (this->MoveToFirst(); !this->IsOut(); this->MoveToNext())
{
if (this->GetCurData() == t)
{
DelCur();
return 1;
}
}
return 0;
}
template<class T>
T* XPDList<T>::FetchCur()
{
if (this->IsOut())
{
return NULL;
}
T* p = this->GetCurData();
this->SetCurData(NULL);
DelCur();
return p;
}
template<class T>
bool XPDList<T>::IsEmptyData(long index)const
{
return this->IsValidIndex(index) ? this->GetAt(index) == NULL : true;
}
template<class T>
void XPDList<T>::ReleaseCur()
{
if (IsCurEmpty())
{
return;
}
delete this->GetCurData();
this->SetCurData(NULL);
}
template<class T>
long XPDList<T>::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<class T>
void XPDList<T>::FindDataOrInsertHead(const T&t)
{
long pos = FindData(t,0,this->GetLastIndex());
if (pos == NOT_FOUND)
{
T*p = new T;
*p = t;
this->InsertHead(p);
}
}
#endif