643 lines
10 KiB
C++
643 lines
10 KiB
C++
#pragma once
|
|
#include "SHTable.h"
|
|
#include "SHListNode.h"
|
|
|
|
template<class T> class SHTable;
|
|
|
|
template<class T> class SHList:public SHTable<T>
|
|
{
|
|
public:
|
|
SHList(long initLength = 0);
|
|
SHList(const SHTable<T>&table);
|
|
SHList(const SHList<T>&table);
|
|
SHList<T>&operator = (const SHTable<T>&table);
|
|
SHList<T>&operator = (const SHList<T>&table);
|
|
virtual ~SHList();
|
|
|
|
//space manage
|
|
//when newLength<old length,cur will move to last!always copy!
|
|
virtual void SetLength(long newLength,bool bCopy = true);
|
|
|
|
//cur visit
|
|
//allow get head node data!
|
|
virtual T& GetCurData();
|
|
|
|
//alloc set head node data!
|
|
virtual void SetCurData(const T&t);
|
|
|
|
//when index invalid,move to head;
|
|
virtual void MoveTo(long index);
|
|
|
|
//if list is empty,move to head node;
|
|
virtual void MoveToFirst();
|
|
|
|
//if list is empty,move to head node;
|
|
virtual void MoveToLast();
|
|
|
|
//to recycle include head node;
|
|
virtual void MoveToNext();
|
|
|
|
//to recycle include head node;
|
|
virtual void MoveToPre();
|
|
|
|
//const visit
|
|
virtual const T& GetAt(long index) const;
|
|
virtual const T* GetFirst() const;
|
|
virtual const T* GetLast() const;
|
|
virtual const T* GetNext(const T*p) const;
|
|
virtual const T* GetPre(const T*p) const;
|
|
|
|
//insert/del
|
|
//if cur == -1,insert first node;quick speed!
|
|
virtual void InsertAfterCur(const T&t);
|
|
|
|
//alloc cur == -1!slow speed!
|
|
virtual void InsertCur(const T&t);
|
|
|
|
//if cur != -1,don't change cur;if cur == -1,AddTail(T&t),cur move to last!
|
|
//if index == length add tail,if index< = 0,insert first!
|
|
virtual void Insert(long index,const T&t);
|
|
|
|
//insert first!
|
|
virtual void InsertHead(const T&t);
|
|
virtual long AddTail(const T&t);
|
|
|
|
//cur node can't be head node!!!
|
|
virtual void DelCur();
|
|
|
|
virtual void Clear();
|
|
|
|
//detach but not release
|
|
virtual void DetachAfterCur();
|
|
|
|
virtual long Conbine(SHList<T>&list,long from = 0);
|
|
|
|
//operato
|
|
//稳定插入排序
|
|
virtual void Arrange(bool bIncrease = true);
|
|
|
|
//稳定插入排序
|
|
virtual void Arrange(int (*cmp)(const T&,const T&));
|
|
|
|
//比SHTable::Reverse快的多!
|
|
virtual void ReverseList();
|
|
|
|
virtual void Rotate(long iFrom,long iTo);
|
|
|
|
void Detach();
|
|
void DetachAfter(long i);
|
|
void SplitAtCur(SHList<T>&list);
|
|
void SplitAt(long i,SHList<T>&list);
|
|
SHListNode<T>*GetCurPos() const;
|
|
|
|
protected:
|
|
|
|
//head node,not the first data node;
|
|
SHListNode<T>*head;
|
|
|
|
//last node,when is empty it is head node;
|
|
SHListNode<T>*tail;
|
|
|
|
//the node whose index is cur,when cur is -1,curPos is head.
|
|
SHListNode<T>*curPos;
|
|
|
|
virtual void Realloc(long newLength);
|
|
|
|
};
|
|
|
|
template<class T>
|
|
SHList<T>& SHList<T>::operator = (const SHTable<T>&table)
|
|
{
|
|
DeepCopy(table);
|
|
return *this;
|
|
}
|
|
|
|
template<class T>
|
|
SHList<T>& SHList<T>::operator = (const SHList<T>&table)
|
|
{
|
|
DeepCopy(table);
|
|
return *this;
|
|
}
|
|
|
|
template<class T>
|
|
void SHList<T>::Detach()
|
|
{
|
|
curPos = head;
|
|
this->cur = -1;
|
|
DetachAfterCur();
|
|
}
|
|
|
|
template<class T>
|
|
void SHList<T>::DetachAfter(long i)
|
|
{
|
|
MoveTo(i);
|
|
DetachAfterCur();
|
|
}
|
|
|
|
template<class T>
|
|
void SHList<T>::SplitAtCur(SHList<T>&list)
|
|
{
|
|
list.Conbine(*this,this->cur);
|
|
}
|
|
|
|
template<class T>
|
|
void SHList<T>::SplitAt(long i,SHList<T>&list)
|
|
{
|
|
MoveTo(i);
|
|
SplitAtCur(list);
|
|
}
|
|
|
|
template<class T>
|
|
SHListNode<T>* SHList<T>::GetCurPos() const
|
|
{
|
|
return curPos;
|
|
}
|
|
|
|
template<class T>
|
|
void SHList<T>::DetachAfterCur()
|
|
{
|
|
curPos->next = head;
|
|
tail = curPos;
|
|
this->length = this->cur + 1;
|
|
}
|
|
|
|
template<class T>
|
|
T& SHList<T>::GetCurData()
|
|
{
|
|
return curPos->data;
|
|
}
|
|
|
|
template<class T>
|
|
void SHList<T>::SetCurData(const T&t)
|
|
{
|
|
curPos->data = t;
|
|
}
|
|
|
|
template<class T>
|
|
void SHList<T>::Clear()
|
|
{
|
|
tail->next = NULL;
|
|
SHListNode<T>*p = head->next;
|
|
while(p != NULL)
|
|
{
|
|
SHListNode<T> *pn = p->next;
|
|
delete p;
|
|
p = pn;
|
|
}
|
|
curPos = tail = head->next = head;
|
|
this->length = 0;
|
|
this->cur = -1;
|
|
}
|
|
|
|
template<class T>
|
|
const T* SHList<T>::GetFirst() const
|
|
{
|
|
return this->IsEmpty() ? NULL : (const T*)(head->next);
|
|
}
|
|
|
|
template<class T>
|
|
const T* SHList<T>::GetLast() const
|
|
{
|
|
return this->IsEmpty() ? NULL : (const T*)tail;
|
|
}
|
|
|
|
template<class T>
|
|
const T* SHList<T>::GetNext(const T*p) const
|
|
{
|
|
return (p == NULL || p == ((const T*)tail)) ? NULL : (const T*)(((const SHListNode<T>*)p)->next);
|
|
}
|
|
|
|
template<class T>
|
|
const T*SHList<T>::GetPre(const T*p) const
|
|
{
|
|
if (p == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
if (p == ((const T*)(head->next)))
|
|
{
|
|
return NULL;
|
|
}
|
|
else if (p == (const T*)(curPos->next))
|
|
{
|
|
return (const T*)curPos;
|
|
}
|
|
|
|
long i = 0;
|
|
for (const SHListNode<T>*pCur = head;i<this->GetLength();i++,pCur = pCur->next)
|
|
{
|
|
if ((const T*)(pCur->next) == p)
|
|
{
|
|
return (const T*)pCur;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
template<class T>
|
|
const T& SHList<T>::GetAt(long index) const
|
|
{
|
|
SHListNode<T> *p;
|
|
if (index>this->cur)
|
|
{
|
|
p = curPos;
|
|
for (long i = this->cur;i<index;i++,p = p->next);
|
|
}
|
|
else if (index<this->cur)
|
|
{
|
|
p = head;
|
|
for (long i = -1;i<index;i++,p = p->next);
|
|
}
|
|
else
|
|
{
|
|
p = curPos;
|
|
}
|
|
return p->data;
|
|
}
|
|
|
|
template<class T>
|
|
void SHList<T>::ReverseList()
|
|
{
|
|
if (this->length < 2)
|
|
{
|
|
return;
|
|
}
|
|
|
|
SHListNode<T>*p,*next = head->next,*pre = head;
|
|
for (long i = 0;i<this->length;i++)
|
|
{
|
|
p = next;
|
|
next = p->next;
|
|
p->next = pre;
|
|
pre = p;
|
|
}
|
|
p = head->next;
|
|
head->next = tail;
|
|
tail = p;
|
|
}
|
|
|
|
template<class T>
|
|
void SHList<T>::Rotate(long iFrom,long iTo)
|
|
{
|
|
if (iFrom != iTo)
|
|
{
|
|
long iNewZero = (iFrom - iTo + this->GetLength()) % this->GetLength();
|
|
MoveTo(iNewZero - 1 + this->GetLength() % this->GetLength());
|
|
SHListNode<T>*newTail = GetCurPos();
|
|
MoveTo(iNewZero);
|
|
|
|
//形成环路
|
|
tail->next = head->next;
|
|
|
|
//更新head
|
|
head->next = curPos;
|
|
this->cur = 0;
|
|
|
|
//更新tail
|
|
tail = newTail;
|
|
tail->next = head;
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
void SHList<T>::Arrange(bool bIncrease)
|
|
{
|
|
if (this->GetLength() < 2)
|
|
{
|
|
return;
|
|
}
|
|
if (bIncrease)
|
|
{
|
|
MoveToFirst();
|
|
MoveToNext();
|
|
while(!this->IsBegin())
|
|
{
|
|
T temp = GetCurData();
|
|
long i = this->GetCur();
|
|
SHListNode<T>*pos = GetCurPos();
|
|
MoveToFirst();
|
|
SHListNode<T>*pre = head;
|
|
long preCur = -1;
|
|
while(this->GetCur() < i)
|
|
{
|
|
if (GetCurData()>temp)
|
|
{
|
|
curPos = pre;
|
|
this->cur = preCur;
|
|
InsertAfterCur(temp);
|
|
curPos = pos;
|
|
this->cur = i+1;
|
|
DelCur();
|
|
}
|
|
else
|
|
{
|
|
preCur = this->GetCur();
|
|
pre = GetCurPos();
|
|
MoveToNext();
|
|
}
|
|
}
|
|
MoveToNext();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MoveToFirst();
|
|
MoveToNext();
|
|
while(!this->IsBegin())
|
|
{
|
|
T temp = GetCurData();
|
|
long i = this->GetCur();
|
|
SHListNode<T>*pos = GetCurPos();
|
|
MoveToFirst();
|
|
SHListNode<T>*pre = head;
|
|
long preCur = -1;
|
|
while(this->GetCur()<i)
|
|
{
|
|
if (GetCurData()<temp)
|
|
{
|
|
curPos = pre;
|
|
this->cur = preCur;
|
|
InsertAfterCur(temp);
|
|
curPos = pos;
|
|
this->cur = i+1;
|
|
DelCur();
|
|
}
|
|
else
|
|
{
|
|
preCur = this->GetCur();
|
|
pre = GetCurPos();
|
|
MoveToNext();
|
|
}
|
|
}
|
|
MoveToNext();
|
|
}
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
void SHList<T>::Arrange(int (*cmp)(const T&,const T&))
|
|
{
|
|
if (this->GetLength() < 2)
|
|
{
|
|
return;
|
|
}
|
|
|
|
MoveToFirst();
|
|
MoveToNext();
|
|
while(!this->IsBegin())
|
|
{
|
|
T temp = GetCurData();
|
|
long i = this->GetCur();
|
|
SHListNode<T>*pos = GetCurPos();
|
|
MoveToFirst();
|
|
SHListNode<T>*pre = head;
|
|
long preCur = -1;
|
|
while(this->GetCur()<i)
|
|
{
|
|
if (cmp(GetCurData(),temp)>0)
|
|
{
|
|
curPos = pre;
|
|
this->cur = preCur;
|
|
InsertAfterCur(temp);
|
|
curPos = pos;
|
|
this->cur = i+1;
|
|
DelCur();
|
|
}
|
|
else
|
|
{
|
|
preCur = this->GetCur();
|
|
pre = GetCurPos();
|
|
MoveToNext();
|
|
}
|
|
}
|
|
MoveToNext();
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
void SHList<T>::MoveToFirst()
|
|
{
|
|
if (this->IsEmpty())
|
|
{
|
|
curPos = head;
|
|
this->cur = -1;
|
|
}
|
|
else
|
|
{
|
|
curPos = head->next;
|
|
this->cur = 0;
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
void SHList<T>::MoveToLast()
|
|
{
|
|
curPos = tail;
|
|
this->cur = this->length-1;
|
|
}
|
|
|
|
template<class T>
|
|
void SHList<T>::MoveToPre()
|
|
{
|
|
if (this->GetCur() == -1)
|
|
{
|
|
MoveToLast();
|
|
}
|
|
else
|
|
{
|
|
MoveTo(this->GetCur() - 1);
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
void SHList<T>::MoveToNext()
|
|
{
|
|
curPos = curPos->next;
|
|
this->cur++;
|
|
if (curPos == head)
|
|
{//recycle
|
|
this->cur = -1;
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
void SHList<T>::MoveTo(long index)
|
|
{
|
|
if (this->IsValidIndex(index))
|
|
{
|
|
if (index == this->GetLastIndex())
|
|
{
|
|
MoveToLast();
|
|
}
|
|
else
|
|
{
|
|
if (index < this->cur)
|
|
{//before
|
|
MoveToFirst();
|
|
}
|
|
while(this->GetCur() != index)
|
|
{
|
|
MoveToNext();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this->cur = -1;
|
|
curPos = head;
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
void SHList<T>::InsertAfterCur(const T&t)
|
|
{
|
|
SHListNode<T>*p = new SHListNode<T>;
|
|
p->data = t;
|
|
p->next = curPos->next;
|
|
curPos->next = p;
|
|
this->length++;
|
|
this->cur++;
|
|
if (curPos == tail)
|
|
{
|
|
tail = p;
|
|
}
|
|
curPos = p;
|
|
}
|
|
|
|
template<class T>
|
|
void SHList<T>::InsertCur(const T&t)
|
|
{
|
|
MoveToPre();
|
|
InsertAfterCur(t);
|
|
}
|
|
|
|
template<class T>
|
|
long SHList<T>::AddTail(const T&t)
|
|
{
|
|
MoveToLast();
|
|
InsertAfterCur(t);
|
|
return this->GetLastIndex();
|
|
}
|
|
|
|
template<class T>
|
|
void SHList<T>::InsertHead(const T&t)
|
|
{
|
|
MoveTo(-1);
|
|
InsertAfterCur(t);
|
|
}
|
|
|
|
template<class T>
|
|
void SHList<T>::Insert(long index,const T&t)
|
|
{
|
|
MoveTo(index-1);
|
|
InsertAfterCur(t);
|
|
}
|
|
|
|
template<class T>
|
|
void SHList<T>::DelCur()
|
|
{
|
|
SHListNode<T>*p = curPos;
|
|
MoveToPre();
|
|
curPos->next = p->next;
|
|
if (p == tail)
|
|
{
|
|
tail = curPos;
|
|
}
|
|
delete p;
|
|
this->length--;
|
|
}
|
|
|
|
template<class T>
|
|
void SHList<T>::Realloc(long newLength)
|
|
{
|
|
if (newLength>this->GetLength())
|
|
{
|
|
long oldCur = this->cur;
|
|
SHListNode<T>*oldPos = curPos;
|
|
T t;
|
|
while(this->GetLength()<newLength)
|
|
{
|
|
AddTail(t);
|
|
}
|
|
curPos = oldPos;
|
|
this->cur = oldCur;
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
void SHList<T>::SetLength(long newLength,bool bCopy)
|
|
{
|
|
if (newLength>this->GetLength())
|
|
{
|
|
Realloc(newLength);
|
|
}
|
|
else
|
|
{
|
|
while(newLength<this->GetLength())
|
|
{
|
|
this->DelTail();
|
|
}
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
SHList<T>::SHList(long initLength)
|
|
{
|
|
head = tail = new SHListNode<T>;
|
|
head->next = head;
|
|
curPos = head;
|
|
Realloc(initLength);
|
|
}
|
|
|
|
template<class T>
|
|
SHList<T>::SHList(const SHTable<T>&table)
|
|
{
|
|
head = tail = new SHListNode<T>;
|
|
head->next = head;
|
|
curPos = head;
|
|
DeepCopy(table);
|
|
}
|
|
|
|
template<class T>
|
|
SHList<T>::SHList(const SHList<T>&table)
|
|
{
|
|
head = tail = new SHListNode<T>;
|
|
head->next = head;
|
|
curPos = head;
|
|
DeepCopy(table);
|
|
}
|
|
|
|
template<class T>
|
|
SHList<T>::~SHList()
|
|
{
|
|
if (head == NULL)
|
|
{
|
|
return;
|
|
}
|
|
Clear();
|
|
delete head;
|
|
}
|
|
|
|
template<class T>
|
|
long SHList<T>::Conbine(SHList<T>&lstConbine,long from)
|
|
{
|
|
if (lstConbine.IsValidIndex(from))
|
|
{
|
|
long oldCur = this->GetCur();
|
|
SHListNode<T>* oldPos = GetCurPos();
|
|
|
|
lstConbine.MoveTo(from);
|
|
tail->next = lstConbine.GetCurPos();
|
|
lstConbine.MoveToLast();
|
|
tail = lstConbine.GetCurPos();
|
|
this->length += lstConbine.GetLength() - from;
|
|
lstConbine.DetachAfter(from- 1);
|
|
tail->next = head;
|
|
|
|
this->cur = oldCur;
|
|
curPos = oldPos;
|
|
}
|
|
return this->length;
|
|
}
|
|
|