C++语言实现顺序表

C++语言实现顺序表

顺序表的定义及其特点

顺序表的定义是:把线性表中的所有表项按照其逻辑顺序依次存储到从计算机存储中指定存储位置开始的一块连续的存储空间中。 这样,线性表中第一个表项的存储位置就是被指定的存储位置,第i个表项(2\leq i \leqn)的存储位置紧接在第i一1个表项的存储位置的后面。假设顺序表中每个表项的数据类型为T,则每个表项所占用存储空间的大小(即字节数)大小相同,均为 sizeof(T),整个顺序表所占用存储空间的大小为n\times sizeof(T),其中n表示线性表的长度。

顺序表的特点是:

(1)在顺序表中,各个表项的逻辑顺序与其存放的物理顺序一致,即第i个表项存储于
第i个物理位置(1\leq i \leqn).
(2)对顺序表中所有表项,既可以进行顺序访问,也可以进行随机访问。 也就是说,既可以从表的第一个表项开始逐个访问表项,也可以按照表项的序号(亦称为下标)直接访问表项。

顺序表类定义及其主要操作

顺序表的类声明
class SeqList
{
    private:
        T *data;//存放数据的动态数组
        int maxSize;//最大可容纳表项的项数
        int last; //当前已存表项的最后位置(从0开始)
        void reSize(int newSize);   //改变数组空间大小
        
    public:
        SeqList(int sz);          //构造函数
        SeqList(SeqList<T>& L);            //复制构造函数
        ~SeqList() {delete[ ] data;}            //析构函数
        int Size(){//求表最大容量
            return maxSize;
            }    
        int Length() {//计算表长度
            return last+1;
            }        
        int Search(T x);//搜索x在表中位置,函数返回表项序号 
        int Locate(int i);//定位第i个表项,函数返回表项序号
        bool Insert(int i, T& x);//插入x在第i个表项之后
        bool Remove(int i, T& x);//删除第i个表项之后,通过x返回表项的值
        bool GetData(int i,T& x);//取第i个表项的值,以x引用返回
        bool SetData(int i,T& x);//用x修改第i个表项的值
        bool IsEmpty(){//判断表是否空否,是返回true,否返回false
            return (last==-1) ? true : false;
        }
        bool IsFull(){//判读表是否满否,是返回true,否返回false
            return (last = maxSize - 1) ? true : false;
        }
        void input();//输入数据
        void output();//打印数据
};

构造函数和复制构造函数
template <class T>
inline SeqList<T>::SeqList(int sz)
{
    if (sz > 0) {
        maxSize = sz;  last = -1;
        data = new T[maxSize];     //创建表存储数组
        if (data == NULL)          //动态分配失败
        { 
            cout<<"储存分配错误!"<<endl;
        }
    }
}
template <class T>
inline SeqList<T>::SeqList(SeqList<T>& L)
{
    //复制构造函数,用参数表中给出的已有顺序表初始化新建的顺序表
    maxSize = L.Size();
    last = L.Length()-1;
    T value;
    data = new T[maxSize];//创建顺序表储存数组
    if(data == NULL){
        cout<<"动态分配错误!"<<endl;
    }
    for(int i =1;i<=last-1;i++){
        L.GetData(i, value);
        data[i-1] = value;
    }
    
}

调整顺序表空间大小
template <class T>
inline void SeqList<T>::reSize(int newSize){
    //私有函数,扩充顺序表的储存数组空间的大小,新数组的元素个数为newSize.
    if(newSize <= 0){
        cout<<"无效数组的大小!"<<endl;
    }
    if(newSize != maxSize){
        T *newarray = new T[newSize];
        if(newarray == NULL){
            cout<<"储存分配错误!"<<endl;
        }
        int n = last+1;
        T *srcptr = data;//源数组的首地址
        T *desptr = newarray;//目的数组的首地址
        while(n--){//复制
            *desptr++ = *srcptr++;
        }
        delete []data;//删除老数组
        data = newarray;
        maxSize = newSize;//复制新数组
    }
}

搜索和定位操作
template <class T>
inline int SeqList<T>::Search(T x)
{
    //搜索函数:在表中顺序搜索与给定值x匹配的表项,找到则函数返回该表项是第几个元素
    //否则返回0,表示搜索失败
    for(int i=0;i<=last;i++){
        if(data[i] == x)
        return i+1;
    }
    return 0;
}
template <class T>
inline int SeqList<T>::Locate(int i)
{
    //定位函数:返回第i(1<=i<=lat+1)个表项的位置,否则函数返回0,表示定位失败
    if(i>=1 && i<last+1){
        return i;
    }
    else return 0;
}

插入与删除操作
template <class T>
inline bool SeqList<T>::Insert(int i, T& x)//插入x在第i个表项之后
{
    //将新元素x插入到第i(0<=i<=last+1)个表项之后。函数返回插入成功的信息,若插入成功返回true,否则返回false.
    //i=0时虚拟的,实际上是插入到第1个元素的位置。
    if(last == maxSize - 1){
        return false;//表满,不能插入
    }
    if(i<0 || i > last+1)
    {
        return false;//参数i不合理,不能插入
    }
    for(int j=last;j>=i;j--)
    {
        data[j+1]=data[j];//一次后移,空出第i号位置
    }
    data[i] = x;//插入
    last++;//最后位置加一
    return true;
}
template <class T>
inline bool SeqList<T>::Remove(int i, T& x)//删除第i个表项之后,通过x返回表项的值
{
    //从表中删除第i(0<=i<=last+1)个表项,通过引用型参数x返回删除的元素值。函数返回删除成功的信息,删除成功返回true,删除失败返回false
    if(last == -1){
        return false;//表空,不能删除
    }
    if(i<1 || i>last+1){
        return false;//参数i不合理,不能删除
    }
    x=data[i];//储存删除的元素
    for(int j=i;j<=last;j++)
    {
        data[j-1] = data[j];//依次前移,填补
    }
    last--;//最后位置减一
    return true;
}

顺序表的性能分析

顺序表所有操作的实现中,最复杂、最耗时的就是搜索、插入和删除运算的实现代码。分析顺序表的性能,主要是分析这3个操作的实现代码的时间复杂性。
int search(T& x)是顺序表的顺序搜索算法。 其主要思想是:

从表的开始位置起,根据给定值x,逐个与表中各表项的值进行比较。 若给定值与某个表项的值相等,则算法报告搜索成功的信息并返回该表项的位置;若查遍表中所有的表项,没有任何一个表项满足要求,则算法报告搜索不成功的信息并返回0(必要的话,可改一下算法,返回新表项应插人的位置)。

搜索算法的时间代价用数据比较次数来衡量。 在搜索成功的情形下,顺序搜索的数据比较次数可做如下分析。 若要找的正好是表中第1个表项,数据比较次数为1,这是最好情况;若要找的是表中最后的第n个表项,数据比较次数为n(设表的长度为n),这是最坏的情况 。若要计算平均数据比较次数,需要考虑各个表项的搜索概率p及找到该表项时的数据比较次数p_i.搜索的平均数据比较次数ACN(average comparing number)为
ACN=\sum_{i=1}^n {p_i}\times c_i

计算平均数据比较次数是为了了解对表操作的整体性能。若考虑相等概率的情形。搜索各表项的可能性相同,有p_1=p_2=...=p_n=\frac1 n,且搜索第1个表项的数据比较次数为1,搜计算平均值是为了解算法对表操作的整体性能。 若仅考虑相等概率的情形。搜索各表索第2个表项的数据比较次数为2,,搜索第i号表项的数据比较次数为i,则
ACN=\frac1 n\sum_{i=1}^ni=\frac1 n(1+2+3+...+n)==\frac{1+n} 2
即平均要比较\frac{n+1} 2个表项。

分析顺序表的插入和删除的时间代价主要看循环内的数据移动次数
在将新表项插入到第i个表项(0\leq i \leqn)后面时,必须从后向前循环,逐个向后移动n-i个表项。 因此,最好的情形是在第n个表项后追加新表项,移动表项个数为0;最差情形是在第1个表项位置插人新表项(视为在第0个表项后面插入),移动表项个数为n;平均数据移动次数AMN(average moving number)在各表项插入概率相等时为
AMN=\frac1 {n+1}\sum_{i=0}^n{(n-i)}=\frac1 {n+1}\frac{n (n+1)} 2=\frac n 2
即就整体性能来说,在插入时有n+1个插入位置,平均移动\frac n 2个表项!

在删除第i个表项(1\leq i \leqn)时,必须从前向后循环,逐个移动n一i个表项。 因此,最好的情形是删去最后的第n个表项,移动表项个数为0;最差情形是删去第1个表项,移动项个数为n-1;平均数据移动次数AMN在各表项删除概率相等时为
AMN=\frac1 n\sum_{i=1}^n{(n-i)}=\frac1 {n}\frac{n (n-1)} 2=\frac {n-1} 2
就整体性能来说,在删除时有n个删除位置,平均移动(n-1)/2个表项。

以上是C++顺序表使用过程中最常用的主要操作,相关完整代码已经push到GitHub,需要的小伙伴自行clone,如果觉得还不错的话,欢迎Star,这里是传送门C++顺序表,除此之外,想要了解更多的C,C++,Java,Python等相关知识的童鞋,欢迎来我的博客相逢的博客,我们一起讨论!接下来我会更新C语言链式结构实现线性表,敬请期待!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容