661 lines
11 KiB
C++
661 lines
11 KiB
C++
//-------------------------------------------------------------------------------------------------------+
|
|
// Copyright (C), 1998-2007, SH Software Co. Ltd.
|
|
// = FileName : List 模板类
|
|
// = Version : ver2.0
|
|
// = Author : zjq
|
|
// = CreateDate : 2002-09-09
|
|
// = Description: List 声明 单向循环链表
|
|
// 支持自动分配,使用[]可以将其看作一个具有无限长度的链表,同时优化了链表的随机访问速度。
|
|
// = Maintainers:
|
|
//
|
|
//-------------------------------------------------------------------------------------------------------+
|
|
#ifndef _LIST_H_
|
|
#define _LIST_H_
|
|
|
|
#ifndef _TABLE_H_
|
|
#include "Table.h"
|
|
#endif
|
|
|
|
#ifndef _LISTNODE_H_
|
|
#include "ListNode.h"
|
|
#endif
|
|
|
|
template<class T> class List:public Table<T>
|
|
{
|
|
public:
|
|
List(long initLength = 0);
|
|
List(const Table<T>&table);
|
|
List(const List<T>&table);
|
|
List<T>&operator = (const Table<T>&table);
|
|
List<T>&operator = (const List<T>&table);
|
|
virtual ~List();
|
|
|
|
//space manage
|
|
//when newLength<old this->length,this->cur will move to last!always copy!
|
|
virtual void SetLength(long newLength,bool bCopy = true);
|
|
|
|
//this->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 this->cur == -1,insert first node;quick speed!
|
|
virtual void InsertAfterCur(const T&t);
|
|
|
|
//alloc this->cur == -1!slow speed!
|
|
virtual void InsertCur(const T&t);
|
|
|
|
//if this->cur != -1,don't change this->cur;if this->cur == -1,AddTail(T&t),this->cur move to last!
|
|
//if index == this->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);
|
|
|
|
//this->cur node can't be head node!!!
|
|
virtual void DelCur();
|
|
|
|
virtual void Clear();
|
|
|
|
//detach but not release
|
|
virtual void DetachAfterCur();
|
|
|
|
virtual long Conbine(List<T>&list,long from = 0);
|
|
|
|
//operato
|
|
//稳定插入排序
|
|
virtual void Arrange(bool bIncrease = true);
|
|
|
|
//稳定插入排序
|
|
virtual void Arrange(int (*cmp)(const T&,const T&));
|
|
|
|
//比Table::Reverse快的多!
|
|
virtual void ReverseList();
|
|
|
|
virtual void Rotate(long iFrom,long iTo);
|
|
|
|
void Detach();
|
|
void DetachAfter(long i);
|
|
void SplitAtCur(List<T>&list);
|
|
void SplitAt(long i,List<T>&list);
|
|
ListNode<T>*GetCurPos() const;
|
|
|
|
protected:
|
|
|
|
//head node,not the first data node;
|
|
ListNode<T>*head;
|
|
|
|
//last node,when is empty it is head node;
|
|
ListNode<T>*tail;
|
|
|
|
//the node whose index is this->cur,when this->cur is -1,curPos is head.
|
|
ListNode<T>*curPos;
|
|
|
|
virtual void Realloc(long newLength);
|
|
|
|
};
|
|
|
|
template<class T>
|
|
List<T>& List<T>::operator = (const Table<T>&table)
|
|
{
|
|
this->DeepCopy(table);
|
|
return *this;
|
|
}
|
|
|
|
template<class T>
|
|
List<T>& List<T>::operator = (const List<T>&table)
|
|
{
|
|
this->DeepCopy(table);
|
|
return *this;
|
|
}
|
|
|
|
template<class T>
|
|
void List<T>::Detach()
|
|
{
|
|
this->curPos = this->head;
|
|
this->cur = -1;
|
|
DetachAfterCur();
|
|
}
|
|
|
|
template<class T>
|
|
void List<T>::DetachAfter(long i)
|
|
{
|
|
MoveTo(i);
|
|
DetachAfterCur();
|
|
}
|
|
|
|
template<class T>
|
|
void List<T>::SplitAtCur(List<T>&list)
|
|
{
|
|
list.Conbine(*this,this->cur);
|
|
}
|
|
|
|
template<class T>
|
|
void List<T>::SplitAt(long i,List<T>&list)
|
|
{
|
|
MoveTo(i);
|
|
SplitAtCur(list);
|
|
}
|
|
|
|
template<class T>
|
|
ListNode<T>* List<T>::GetCurPos() const
|
|
{
|
|
return this->curPos;
|
|
}
|
|
|
|
template<class T>
|
|
void List<T>::DetachAfterCur()
|
|
{
|
|
this->curPos->next =this-> head;
|
|
this->tail = this->curPos;
|
|
this->length = this->cur + 1;
|
|
}
|
|
|
|
template<class T>
|
|
T& List<T>::GetCurData()
|
|
{
|
|
return this->curPos->data;
|
|
}
|
|
|
|
template<class T>
|
|
void List<T>::SetCurData(const T&t)
|
|
{
|
|
this->curPos->data = t;
|
|
}
|
|
|
|
template<class T>
|
|
void List<T>::Clear()
|
|
{
|
|
this->tail->next = NULL;
|
|
ListNode<T>*p = this->head->next;
|
|
while(p != NULL)
|
|
{
|
|
ListNode<T> *pn = p->next;
|
|
delete p;
|
|
p = pn;
|
|
}
|
|
this->curPos = this->tail = this->head->next = this->head;
|
|
this->length = 0;
|
|
this->cur = -1;
|
|
}
|
|
|
|
template<class T>
|
|
const T* List<T>::GetFirst() const
|
|
{
|
|
return this->IsEmpty() ? NULL : (const T*)(this->head->next);
|
|
}
|
|
|
|
template<class T>
|
|
const T* List<T>::GetLast() const
|
|
{
|
|
return this->IsEmpty() ? NULL : (const T*)this->tail;
|
|
}
|
|
|
|
template<class T>
|
|
const T* List<T>::GetNext(const T*p) const
|
|
{
|
|
return (p == NULL || p == ((const T*)this->tail)) ? NULL : (const T*)(((const ListNode<T>*)p)->next);
|
|
}
|
|
|
|
template<class T>
|
|
const T*List<T>::GetPre(const T*p) const
|
|
{
|
|
if (p == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
if (p == ((const T*)(this->head->next)))
|
|
{
|
|
return NULL;
|
|
}
|
|
else if (p == (const T*)(this->curPos->next))
|
|
{
|
|
return (const T*)this->curPos;
|
|
}
|
|
|
|
long i = 0;
|
|
for (const ListNode<T>*pCur = this->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& List<T>::GetAt(long index) const
|
|
{
|
|
ListNode<T> *p;
|
|
if (index>this->cur)
|
|
{
|
|
p = this->curPos;
|
|
for (long i = this->cur;i<index;i++,p = p->next);
|
|
}
|
|
else if (index<this->cur)
|
|
{
|
|
p = this->head;
|
|
for (long i = -1;i<index;i++,p = p->next);
|
|
}
|
|
else
|
|
{
|
|
p = this->curPos;
|
|
}
|
|
return p->data;
|
|
}
|
|
|
|
template<class T>
|
|
void List<T>::ReverseList()
|
|
{
|
|
if (this->length < 2)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ListNode<T>*p,*next = this->head->next,*pre = this->head;
|
|
for (long i = 0;i<this->length;i++)
|
|
{
|
|
p = next;
|
|
next = p->next;
|
|
p->next = pre;
|
|
pre = p;
|
|
}
|
|
p = this->head->next;
|
|
this->head->next = this->tail;
|
|
this->tail = p;
|
|
}
|
|
|
|
template<class T>
|
|
void List<T>::Rotate(long iFrom,long iTo)
|
|
{
|
|
if (iFrom != iTo)
|
|
{
|
|
long iNewZero = (iFrom - iTo + this->GetLength()) % this->GetLength();
|
|
MoveTo(iNewZero - 1 + this->GetLength() % this->GetLength());
|
|
ListNode<T>*newTail = GetCurPos();
|
|
MoveTo(iNewZero);
|
|
|
|
//形成环路
|
|
this->tail->next = this->head->next;
|
|
|
|
//更新head
|
|
this->head->next = this->curPos;
|
|
this->cur = 0;
|
|
|
|
//更新tail
|
|
this->tail = newTail;
|
|
this->tail->next = this->head;
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
void List<T>::Arrange(bool bIncrease)
|
|
{
|
|
if (this->GetLength() < 2)
|
|
{
|
|
return;
|
|
}
|
|
if (bIncrease)
|
|
{
|
|
MoveToFirst();
|
|
MoveToNext();
|
|
while(!this->IsBegin())
|
|
{
|
|
T temp = GetCurData();
|
|
long i = this->GetCur();
|
|
ListNode<T>*pos = GetCurPos();
|
|
MoveToFirst();
|
|
ListNode<T>*pre = this->head;
|
|
long preCur = -1;
|
|
while(this->GetCur() < i)
|
|
{
|
|
if (GetCurData()>temp)
|
|
{
|
|
this->curPos = pre;
|
|
this->cur = preCur;
|
|
InsertAfterCur(temp);
|
|
this->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();
|
|
ListNode<T>*pos = GetCurPos();
|
|
MoveToFirst();
|
|
ListNode<T>*pre = head;
|
|
long preCur = -1;
|
|
while(this->GetCur()<i)
|
|
{
|
|
if (GetCurData()<temp)
|
|
{
|
|
this->curPos = pre;
|
|
this->cur = preCur;
|
|
InsertAfterCur(temp);
|
|
this->curPos = pos;
|
|
this->cur = i+1;
|
|
DelCur();
|
|
}
|
|
else
|
|
{
|
|
preCur = this->GetCur();
|
|
pre = GetCurPos();
|
|
MoveToNext();
|
|
}
|
|
}
|
|
MoveToNext();
|
|
}
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
void List<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();
|
|
ListNode<T>*pos = GetCurPos();
|
|
MoveToFirst();
|
|
ListNode<T>*pre = head;
|
|
long preCur = -1;
|
|
while(this->GetCur()<i)
|
|
{
|
|
if (cmp(GetCurData(),temp)>0)
|
|
{
|
|
this->curPos = pre;
|
|
this->cur = preCur;
|
|
InsertAfterCur(temp);
|
|
this->curPos = pos;
|
|
this->cur = i+1;
|
|
DelCur();
|
|
}
|
|
else
|
|
{
|
|
preCur = this->GetCur();
|
|
pre = GetCurPos();
|
|
MoveToNext();
|
|
}
|
|
}
|
|
MoveToNext();
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
void List<T>::MoveToFirst()
|
|
{
|
|
if (this->IsEmpty())
|
|
{
|
|
this->curPos = this->head;
|
|
this->cur = -1;
|
|
}
|
|
else
|
|
{
|
|
this->curPos = this->head->next;
|
|
this->cur = 0;
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
void List<T>::MoveToLast()
|
|
{
|
|
this->curPos = this->tail;
|
|
this->cur = this->length-1;
|
|
}
|
|
|
|
template<class T>
|
|
void List<T>::MoveToPre()
|
|
{
|
|
if (this->GetCur() == -1)
|
|
{
|
|
MoveToLast();
|
|
}
|
|
else
|
|
{
|
|
MoveTo(this->GetCur() - 1);
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
void List<T>::MoveToNext()
|
|
{
|
|
this->curPos = this->curPos->next;
|
|
this->cur++;
|
|
if (this->curPos == this->head)
|
|
{//recycle
|
|
this->cur = -1;
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
void List<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;
|
|
this->curPos = this->head;
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
void List<T>::InsertAfterCur(const T&t)
|
|
{
|
|
ListNode<T>*p = new ListNode<T>;
|
|
p->data = t;
|
|
p->next = this->curPos->next;
|
|
this->curPos->next = p;
|
|
this->length++;
|
|
this->cur++;
|
|
if (this->curPos == this->tail)
|
|
{
|
|
this->tail = p;
|
|
}
|
|
this->curPos = p;
|
|
}
|
|
|
|
template<class T>
|
|
void List<T>::InsertCur(const T&t)
|
|
{
|
|
MoveToPre();
|
|
InsertAfterCur(t);
|
|
}
|
|
|
|
template<class T>
|
|
long List<T>::AddTail(const T&t)
|
|
{
|
|
MoveToLast();
|
|
InsertAfterCur(t);
|
|
return this->GetLastIndex();
|
|
}
|
|
|
|
template<class T>
|
|
void List<T>::InsertHead(const T&t)
|
|
{
|
|
MoveTo(-1);
|
|
InsertAfterCur(t);
|
|
}
|
|
|
|
template<class T>
|
|
void List<T>::Insert(long index,const T&t)
|
|
{
|
|
MoveTo(index-1);
|
|
InsertAfterCur(t);
|
|
}
|
|
|
|
template<class T>
|
|
void List<T>::DelCur()
|
|
{
|
|
ListNode<T>*p = this->curPos;
|
|
MoveToPre();
|
|
this->curPos->next = p->next;
|
|
if (p == tail)
|
|
{
|
|
this->tail = this->curPos;
|
|
}
|
|
delete p;
|
|
this->length--;
|
|
}
|
|
|
|
template<class T>
|
|
void List<T>::Realloc(long newLength)
|
|
{
|
|
if (newLength>this->GetLength())
|
|
{
|
|
long oldCur = this->cur;
|
|
ListNode<T>*oldPos = this->curPos;
|
|
T t;
|
|
while(this->GetLength()<newLength)
|
|
{
|
|
AddTail(t);
|
|
}
|
|
this->curPos = oldPos;
|
|
this->cur = oldCur;
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
void List<T>::SetLength(long newLength,bool bCopy)
|
|
{
|
|
if (newLength>this->GetLength())
|
|
{
|
|
Realloc(newLength);
|
|
}
|
|
else
|
|
{
|
|
while(newLength<this->GetLength())
|
|
{
|
|
this->DelTail();
|
|
}
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
List<T>::List(long initLength)
|
|
{
|
|
this->head = this->tail = new ListNode<T>;
|
|
this->head->next = this->head;
|
|
this->curPos = this->head;
|
|
Realloc(initLength);
|
|
}
|
|
|
|
template<class T>
|
|
List<T>::List(const Table<T>&table)
|
|
{
|
|
this->head = this->tail = new ListNode<T>;
|
|
this->head->next = this->head;
|
|
this->curPos = this->head;
|
|
this->DeepCopy(table);
|
|
}
|
|
|
|
template<class T>
|
|
List<T>::List(const List<T>&table)
|
|
{
|
|
this->head = this->tail = new ListNode<T>;
|
|
this->head->next = this->head;
|
|
this->curPos = this->head;
|
|
this->DeepCopy(table);
|
|
}
|
|
|
|
template<class T>
|
|
List<T>::~List()
|
|
{
|
|
if (this->head == NULL)
|
|
{
|
|
return;
|
|
}
|
|
Clear();
|
|
delete this->head;
|
|
}
|
|
|
|
template<class T>
|
|
long List<T>::Conbine(List<T>&list,long from)
|
|
{
|
|
if (list.IsValidIndex(from))
|
|
{
|
|
long oldCur = this->GetCur();
|
|
ListNode<T>* oldPos = GetCurPos();
|
|
|
|
list.MoveTo(from);
|
|
this->tail->next = list.GetCurPos();
|
|
list.MoveToLast();
|
|
this->tail = list.GetCurPos();
|
|
this->length += list.GetLength() - from;
|
|
list.DetachAfter(from- 1);
|
|
this->tail->next = this->head;
|
|
|
|
this->cur = oldCur;
|
|
this->curPos = oldPos;
|
|
}
|
|
return this->length;
|
|
}
|
|
|
|
|
|
#endif
|