1.顺序表的实现
template<typename E>
class AList:public List<E>{
private:
int maxSize;
int listSize;
int curr;//光标落在当前位置的后面
E* listArray;
public:
AList(int size=defaultSize){
maxSize=size;
listSize=curr=0;
listArray=new E[maxSize];
}
~AList(){ delete [] listArray; }
void clear(){
delete [] listArray;
listSize=curr=0;
listArray=new E[maxSize];
}
void insert(const E& it){
Assert(listSize<maxSize,"List capacity exceeded");
for(int i=listSize;i>curr;i--)
listArray[i]=listArray[i-1];
listAray[curr]=it;
listSize++;
}
void append(const E& it){
Assert((curr>=0)&&(curr<listSize),"No element");
E it=listArray[curr];
for(int i=curr;i<listSize-1;i++)
listArray[i]=listArray[i+1];
listSize--;
return it;
}
void moveToStart(){ curr=0; }
void moveToEnd(){ curr=listSize; }
void prev() { if( curr!=0) curr--;}
void next() { if( curr<listSize) curr++;}
int length() const {return listSize;}
int currPos() const {return curr;}
void moveToPos(int pos){
Assert((pos>=0)&&(pos<=listSize),"Pos out of range");
curr=pos;
}
const E& getValue() const {
Assert((curr>=0)&&(curr<listSize),"No current element");
return listArray[curr];
}
};
2.链表实现
光标始终落在curr所代表的当前位置后。
(1)单链表结点类定义
template <typename E> class Link {
public:
E element;
Link *next;
Link(const E& elemval,Link * nextval=NULL)
{ element=elemval; next=nextval;}
Link(Link* nextval=NULL) { next=nextval;}
};
(2)链表实现
template <typename E> class LList:public List<E>{
private:
Link<E>* head;
Link<E>* tail;
Link<E>* curr;
int cnt;
void init(){
curr=tail=head=new Link<E>;
cnt=0;
}
void removeall(){
while(head!=NULL){
curr=head;
head=head->next;
delete curr;
}
}
public:
LList(int size=defaultSize) { init(); }
~LList() { removeall(); }
void print() const;
void clear() { removeall();init(); }
void insert(const E& it){
curr->next=new Link<E>(it,curr->next);
if(tail==curr) tail=curr->next;
cnt++;
}
void append(const E& it){
tail=tail->next=new Link<E>(it,NULL);
cnt++;
}
E remove(){
Assert(curr->next!=NULL,"No element");
E it=curr->next->element;
Link<E>* ltemp=curr->next;
if (tail==curr->next) tail=curr;
curr->next=curr->next->next;
delete ltemp;
cnt--;
return it;
}
void moveToStart() { curr=head; }
void moveToEnd() { curr=tail; }
void prev(){
if(curr==head) return;
Link<E>* temp=head;
while( temp->next!=curr)
temp=temp->next;
curr=temp;
}
void next() { if (curr!=tail) curr=curr->next; }
int length() const { return cnt; }
int currPos() const{
Link<E>* temp=head;
int i;
for(i=0;curr!=temp;i++)
temp=temp->next;
return i;
}
void moveToPos(int pos){
Assert((pos>=0)&&(pos<=cnt),"Position out of range");
curr=head;
for(int i=0;i<pos;i++) curr=curr->next;
}
const E& getValue() const {
Assert(curr->next!=NULL,"No value");
return curr->next->element;
}
};
为缩短线性表的运行时长,可以使用C++操作符重载new和delete.因为重载后的new/delete操作符所需时间约是系统存储分配和回收管理操作的十分之一。重载方法如下:
template <typename E> class Link {
private:
static Link<E>* freelist;
public:
E element;
Link *next;
Link(const E& elemval,Link * nextval=NULL)
{ element=elemval; next=nextval;}
Link(Link* nextval=NULL) { next=nextval;}
void* operator new(size_t){
if(freelist==NULL)
return ::new Link;
Link<E>* temp=freelist;
freelist=freelist->next;
return temp;
}
void operator delete(void* ptr){
((Link<E>*)ptr)->next=freelist;
freelist=(Link<E>*)ptr;
}
};
//The freelist head pointer is actually created here
template <typename E>
Link<E>* Link<E>::freelist=NULL;
(4)顺序表和链表的对比:
*顺序表大小固定,当表中元素只有几个时,浪费很多空间。顺序表的空间需求为Ω(n)
*链表大小灵活,只要存在可用的内存空间分配,个数就没有限制。链表的空间需求为Θ(n)
*顺序表对表中的每一个元素都没有浪费空间,而链表需要在每一个结点上附加一个指针。
*对于取出线性表中某个元素这样的按位置随机访问,顺序表会更快一些;而单链表则不能直接访问前面的元素。
*给出指向链表中合适位置的指针后,链表中insert和remove函数所需要的时间仅用Θ(1),而顺序表则为Θ(n)。
*一般规律:当线性表元素数目变化较大或者未知时,最好使用链表实现;而如果用户事先知道线性表的大致长度,使用顺序表的空间效率会更高。