[数据结构]线性表之顺序表的类模板实现

来源:互联网 发布:淘宝怎么分辨正品店 编辑:程序博客网 时间:2024/04/27 17:00

LinearList.h抽象基类:


#ifndef LINEARLIST#define LINEARLIST//线性表的抽象基类template<class T>class LinearList{public:    LinearList(){};//如果派生类不需要向基类构造函数传递参数,则就会调用基类默认构造函数,所以,要么不写,要么就自己写默认构造函数。    ~LinearList(){};//派生类也会调用基类的析构函数。    virtual int Size()const=0;    virtual int Length()const=0;    virtual int Search(T& x)const=0;    virtual int Locate(int i)const=0;    virtual bool getData(int i,T& x)const=0;    virtual void setData(int i,T& x)=0;    virtual bool Insert(int i,T& x)=0;    virtual bool Remove(int i,T& x)=0;    virtual bool IsEmpty()const=0;    virtual bool IsFull()const=0;    virtual void Sort()=0;    virtual void input()=0;    virtual void output()=0;    //virtual LinearList<T>& operator=(LinearList<T>& L)=0; //在继承类中形参不同,故不能声明纯虚函数,否则继承类无法定义对象。};#endif

实现及测试文件:


/////////////////////////#include"LinearList.h"#include <iostream>#include <cstdlib>using namespace std;const int defaultSize=100;template<class T>class SeqList:public LinearList<T>{protected:    T* data;    int maxSize;    int last;    void reSize(int newSize);public:    SeqList(int sz=defaultSize):data(new T[sz]),maxSize(sz),last(-1){}    SeqList(const SeqList<T>& L);     ~SeqList(){delete []data;}    int Size()const{return maxSize;}    int Length()const{return last+1;}    int Search(T& x)const;    int Locate(int i)const;    bool getData(int i,T& x)const{if(i>0&&i<=last+1){x=data[i-1];return true;}else return false;}    void setData(int i,T& x){if(i>0&&i<=last+1)data[i-1]=x;else {cerr<<"err"<<endl;exit(1);}}    bool Insert(int i,T& x);    bool Remove(int i,T& x);    bool IsEmpty()const{return (last==-1)?true:false;}    bool IsFull()const{return (last==maxSize-1)?true:false;}    void Sort(){};//未提供具体的实现。    void input();    void output();    SeqList<T>& operator=(SeqList<T>& L);};template<class T>SeqList<T>::SeqList(const SeqList<T>& L){    maxSize=L.maxSize;    last=L.last;    data=new T[maxSize];    if(data==NULL){        cerr<<"err"<<endl;        exit(1);    }    T value;    for(int i=0;i<=last;++i){        L.getData(i+1,value);setData(i,value);    }}template<class T>SeqList<T>& SeqList<T>::operator=(SeqList<T>& L){    maxSize=L.maxSize;    last=L.last;    data=new T[maxSize];    if(data==NULL){        cerr<<"err"<<endl;        exit(1);    }    T value;    for(int i=0;i<=last;++i){        L.getData(i+1,value);setData(i,value);    }    return *this;}template<class T>void SeqList<T>::reSize(int newSize){    if(newSize<=0){        cerr<<"err"<<endl;        exit(1);    }    if(newSize!=maxSize){        maxSize=newSize;        T* ptr=new T[maxSize];        if(ptr==NULL){            cerr<<"err"<<endl;            exit(1);        }        T* srcptr=data;        T* destptr=ptr;        n=last+1;        while(n--)            *destptr++=*srcptr++;        delete []data;        data=destptr;    }}template<class T>int SeqList<T>::Search(T& x)const{    for(int i=0;i<=last;++i)        if(data[i]==x)            return i+1;    return 0;}template<class T>int SeqList<T>::Locate(int i)const{    if(i>=1&&i<=last+1)        return i;    else        return 0;}template<class T>bool SeqList<T>::Insert(int i,T& x){    if(i<0||i>last+1)        return false;    if(IsFull())        return false;    for(int j=last;j>=i;--j)        data[j+1]=data[j];    data[i]=x;    ++last;    return true;}template<class T>bool SeqList<T>::Remove(int i,T& x){    if(i<=0||i>last+1)        return false;    if(IsEmpty())        return false;    x=data[i-1];    for(int j=i;j<=last;++j)        data[j-1]=data[j];    --last;    return true;}template<class T>void SeqList<T>::input(){    cout<<"PLZ input element number-1:"<<endl;    while(1){        cin>>last;        if(last<=maxSize-1) break;        cout<<"err! repeat."<<endl;    }    for(int i=0;i<=last;++i)        cin>>data[i];}template<class T>void SeqList<T>::output(){    for(int i=0;i<=last;++i)        cout<<"#"<<i+1<<":"<<data[i]<<"  ";    cout<<endl;}int main(int argc, char* argv[]){    SeqList<int> s(10);    int val=2;    s.input();    s.output();    cout<<"size: "<<s.Size()<<endl;    cout<<"Length: "<<s.Length()<<endl;    cout<<"Search: "<<s.Search(val)<<endl;    cout<<"Locate: "<<s.Locate(2)<<endl;    int val1,val2=99;    s.getData(2,val1);    cout<<"getData: "<<val1<<endl;    s.setData(2,val2);    s.getData(2,val1);    cout<<"setData: "<<val1<<endl;    s.Insert(0,val2);//插入是失败的,因为最初顺序表示满的。    s.output();    s.Remove(2,val1);    s.output();    cout<<"IsEmpty(): "<<s.IsEmpty()<<endl;    cout<<"IsFull: "<<s.IsFull()<<endl;    system("pause");    return 0;}


运行结果:


PLZ input element number-1:
9
0 1 2 3 4 5 6 7 8 9
#1:0  #2:1  #3:2  #4:3  #5:4  #6:5  #7:6  #8:7  #9:8  #10:9
size: 10
Length: 10
Search: 3
Locate: 2
getData: 1
setData: 99
#1:0  #2:99  #3:2  #4:3  #5:4  #6:5  #7:6  #8:7  #9:8  #10:9
#1:0  #2:2  #3:3  #4:4  #5:5  #6:6  #7:7  #8:8  #9:9
IsEmpty(): 0
IsFull: 0
请按任意键继续. . .



要点分析:


1.抽象基类中没有数据成员,只有成员函数的接口,且都是纯虚函数。所以继承类中要实现全部的接口功能,把抽象基类覆盖掉,而且接口要完全相同。

2.抽象基类可以不提供构造和析构函数,这样在派生类中调用系统默认生成的抽象基类构造函数和析构函数。或者你自己定义抽象基类默认的构造函数

和析构函数,也可定义带参数的构造和析构函数,让派生类调用。派生类是必须要调用基类的构造函数和析构函数的,或者显示调用或者隐式调用。

构造函数先调用基类的在调用派生类的,析构函数先调用派生类的在调用基类的。

3.好处是为了利用多态机制。方便使用。

4.只是理论模型,要用于实际还得仔细修改。








1 0
原创粉丝点击