线性表示是由称为元素的数据项组成的一种有限且有序的序列。
下面代码显示了线性表的ADT的定义。
//声明List基类
template <typename E>
class List
{
private:
void operator = (const List &){ }//protect assignment
List(const List&){}
public:
List(){ }//构造函数
virtual ~List(){ } //虚析构函数
/*定义为虚析构函数是为了当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用。
但并不是要把所有类的析构函数都写成虚函数。只有当一个类被用来作为基类的时候,才把析构函数写成虚函数*/
//从列表中清除内容
virtual void clear()=0; //纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法; 含有纯虚拟函数的类称为抽象类,它不能生成对象。
//在当前位置插入一个元素
virtual void insert(const E& item)=0;
//在列表的最后添加一个元素
virtual void append(const E& item)=0;
//移除并返回当前位置的元素
virtual E remove()=0;
//置当前位置的元素为列表第一个位置的元素
virtual void moveToStart()=0;
// 置当前位置的元素为列表最后一个位置的元素
virtual void moveToEnd()=0;
//将当前位置向左移动一步
virtual void prev()=0;
//将当前位置向右移动一步
virtual void next()=0;
//返回列表中元素的个数
virtual int length() const =0;
//返回当前位置
virtual int currPos() const =0;
//移动到某位置
virtual void moveToPos(int pos)=0;
//返回当前元素的值
virtual const E& getValue() const=0;
} ;
根据上述ADT的定义,可以按照如下方式遍历顺序表
for(L.moveToStart();L.currPos()<L.lengeth();L.next())
{
it=L.getValue();
dosomething(it);
}
对于某些参数检查和约束检查,是利用调用Assert函数的形式完成的。以下是Assert的实现代码。
//定义Assert
void Assert(bool val,string s)//if "val" is false, pient "s"
{
if(!val)
{
cout<<"Assertion Failed:"<<s<<endl;
exit(-1);
}
}
如下代码显示了顺序表实现的类说明。AList类继承了抽象类List,实现了List中所有的成员函数。
//顺序表实现
template <typename E>
class AList :public List<E>
{
private:
int maxSize;//列表的最大size
int listSize;//列表元素的个数
int curr; //当前元素的位置
E* listArray; //
public:
AList(int size=1000) //构造函数 默认1000个(自己随便设)
{
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]; //当前位置留出空间,当前位置的后面的元素依次向后挪一
listArray[curr]=it;
listSize++;
}
void append(const E& it)
{
Assert(listSize<maxSize,"List capacity exceeded");
listArray[listSize++]=it;
}
E remove()
{
Assert((curr>=0)&&(curr<listSize),"No element");
E it=listArray[curr];
for(int i=curr;i<listSize;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 //此只能使用于成员函数,意思为此函数里不能函数所在类中的所有成员变量进行修改,他相当于对默认传递到length函数里的this指针加上const的限定,const OneClass * this;
{
return listSize;
}
int currPos() const
{
return curr;
}
void moveToPos(int pos)
{
Assert((pos>=0)&&(pos<=listSize),"Pos out of range"); //pos是可以在listSize位置的
curr=pos;
}
const E& getValue() const
{
Assert((curr>=0)&&(curr<listSize),"No element");
return listArray[curr];
}
} ;
另外一种实现线性表的传统方法是使用指针,即链表。链表是由一系类称为表的结点(node)的对象组成的。其实现代码如下。(此处是单链表,即结点中只能访问后继结点,而没有前驱结点)
//定义Link类
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;
};
};
如下代码显示了链表实现线性表。
//继承List基类,实现LList类
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=1000)
{
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) return;
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),"out of range");
curr=head;
for(int i=0;i<pos;i++)
curr=curr->next;
}
const E& getValue() const
{
Assert(curr->next!=NULL,"no elenment");
return curr->next->element;
}
} ;
因篇幅问题不能全部显示,请点此查看更多更全内容