C++语言实现顺序表

顺序表的定义及其特点

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

顺序表的特点是:

(1)在顺序表中,各个表项的逻辑顺序与其存放的物理顺序一致,即第i个表项存储于

第i个物理位置(1≤\leq≤ i ≤\leq≤n).

(2)对顺序表中所有表项,既可以进行顺序访问,也可以进行随机访问。 也就是说,既可以从表的第一个表项开始逐个访问表项,也可以按照表项的序号(亦称为下标)直接访问表项。

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

顺序表的类声明
  1. class SeqList
  2. {
  3. private:
  4. T *data;//存放数据的动态数组
  5. int maxSize;//最大可容纳表项的项数
  6. int last; //当前已存表项的最后位置(从0开始)
  7. void reSize(int newSize); //改变数组空间大小
  8. public:
  9. SeqList(int sz); //构造函数
  10. SeqList(SeqList<T>& L); //复制构造函数
  11. ~SeqList() {delete[ ] data;} //析构函数
  12. int Size(){//求表最大容量
  13. return maxSize;
  14. }
  15. int Length() {//计算表长度
  16. return last+1;
  17. }
  18. int Search(T x);//搜索x在表中位置,函数返回表项序号
  19. int Locate(int i);//定位第i个表项,函数返回表项序号
  20. bool Insert(int i, T& x);//插入x在第i个表项之后
  21. bool Remove(int i, T& x);//删除第i个表项之后,通过x返回表项的值
  22. bool GetData(int i,T& x);//取第i个表项的值,以x引用返回
  23. bool SetData(int i,T& x);//用x修改第i个表项的值
  24. bool IsEmpty(){//判断表是否空否,是返回true,否返回false
  25. return (last==-1) ? true : false;
  26. }
  27. bool IsFull(){//判读表是否满否,是返回true,否返回false
  28. return (last = maxSize - 1) ? true : false;
  29. }
  30. void input();//输入数据
  31. void output();//打印数据
  32. };
构造函数和复制构造函数
  1. template <class T>
  2. inline SeqList<T>::SeqList(int sz)
  3. {
  4. if (sz > 0) {
  5. maxSize = sz; last = -1;
  6. data = new T[maxSize]; //创建表存储数组
  7. if (data == NULL) //动态分配失败
  8. {
  9. cout<<"储存分配错误!"<<endl;
  10. }
  11. }
  12. }
  13. template <class T>
  14. inline SeqList<T>::SeqList(SeqList<T>& L)
  15. {
  16. //复制构造函数,用参数表中给出的已有顺序表初始化新建的顺序表
  17. maxSize = L.Size();
  18. last = L.Length()-1;
  19. T value;
  20. data = new T[maxSize];//创建顺序表储存数组
  21. if(data == NULL){
  22. cout<<"动态分配错误!"<<endl;
  23. }
  24. for(int i =1;i<=last-1;i++){
  25. L.GetData(i, value);
  26. data[i-1] = value;
  27. }
  28. }
调整顺序表空间大小
  1. template <class T>
  2. inline void SeqList<T>::reSize(int newSize){
  3. //私有函数,扩充顺序表的储存数组空间的大小,新数组的元素个数为newSize.
  4. if(newSize <= 0){
  5. cout<<"无效数组的大小!"<<endl;
  6. }
  7. if(newSize != maxSize){
  8. T *newarray = new T[newSize];
  9. if(newarray == NULL){
  10. cout<<"储存分配错误!"<<endl;
  11. }
  12. int n = last+1;
  13. T *srcptr = data;//源数组的首地址
  14. T *desptr = newarray;//目的数组的首地址
  15. while(n--){//复制
  16. *desptr++ = *srcptr++;
  17. }
  18. delete []data;//删除老数组
  19. data = newarray;
  20. maxSize = newSize;//复制新数组
  21. }
  22. }
搜索和定位操作
  1. template <class T>
  2. inline int SeqList<T>::Search(T x)
  3. {
  4. //搜索函数:在表中顺序搜索与给定值x匹配的表项,找到则函数返回该表项是第几个元素
  5. //否则返回0,表示搜索失败
  6. for(int i=0;i<=last;i++){
  7. if(data[i] == x)
  8. return i+1;
  9. }
  10. return 0;
  11. }
  12. template <class T>
  13. inline int SeqList<T>::Locate(int i)
  14. {
  15. //定位函数:返回第i(1<=i<=lat+1)个表项的位置,否则函数返回0,表示定位失败
  16. if(i>=1 && i<last+1){
  17. return i;
  18. }
  19. else return 0;
  20. }
插入与删除操作
  1. template <class T>
  2. inline bool SeqList<T>::Insert(int i, T& x)//插入x在第i个表项之后
  3. {
  4. //将新元素x插入到第i(0<=i<=last+1)个表项之后。函数返回插入成功的信息,若插入成功返回true,否则返回false.
  5. //i=0时虚拟的,实际上是插入到第1个元素的位置。
  6. if(last == maxSize - 1){
  7. return false;//表满,不能插入
  8. }
  9. if(i<0 || i > last+1)
  10. {
  11. return false;//参数i不合理,不能插入
  12. }
  13. for(int j=last;j>=i;j--)
  14. {
  15. data[j+1]=data[j];//一次后移,空出第i号位置
  16. }
  17. data[i] = x;//插入
  18. last++;//最后位置加一
  19. return true;
  20. }
  21. template <class T>
  22. inline bool SeqList<T>::Remove(int i, T& x)//删除第i个表项之后,通过x返回表项的值
  23. {
  24. //从表中删除第i(0<=i<=last+1)个表项,通过引用型参数x返回删除的元素值。函数返回删除成功的信息,删除成功返回true,删除失败返回false
  25. if(last == -1){
  26. return false;//表空,不能删除
  27. }
  28. if(i<1 || i>last+1){
  29. return false;//参数i不合理,不能删除
  30. }
  31. x=data[i];//储存删除的元素
  32. for(int j=i;j<=last;j++)
  33. {
  34. data[j-1] = data[j];//依次前移,填补
  35. }
  36. last--;//最后位置减一
  37. return true;
  38. }

顺序表的性能分析

顺序表所有操作的实现中,最复杂、最耗时的就是搜索、插入和删除运算的实现代码。分析顺序表的性能,主要是分析这3个操作的实现代码的时间复杂性。

int search(T& x)是顺序表的顺序搜索算法。 其主要思想是:

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

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

ACN=∑i=1npi×ci\sum_{i=1}^n {p_i}\times c_i∑i=1n​pi​×ci​

计算平均数据比较次数是为了了解对表操作的整体性能。若考虑相等概率的情形。搜索各表项的可能性相同,有p1p_1p1​=p2p_2p2​=…=pnp_npn​=1n\frac1 nn1​,且搜索第1个表项的数据比较次数为1,搜计算平均值是为了解算法对表操作的整体性能。 若仅考虑相等概率的情形。搜索各表索第2个表项的数据比较次数为2,搜索第i号表项的数据比较次数为i,则

ACN=1n∑i=1ni=1n(1+2+3+...+n)==1+n2\frac1 n\sum_{i=1}^ni=\frac1 n(1+2+3+...+n)==\frac{1+n} 2n1​∑i=1n​i=n1​(1+2+3+...+n)==21+n​

即平均要比较n+12\frac{n+1} 22n+1​个表项。

分析顺序表的插入和删除的时间代价主要看循环内的数据移动次数

在将新表项插入到第i个表项(0≤\leq≤ i ≤\leq≤n)后面时,必须从后向前循环,逐个向后移动n-i个表项。 因此,最好的情形是在第n个表项后追加新表项,移动表项个数为0;最差情形是在第1个表项位置插人新表项(视为在第0个表项后面插入),移动表项个数为n;平均数据移动次数AMN(average moving number)在各表项插入概率相等时为

AMN=1n+1∑i=0n(n−i)=1n+1n(n+1)2=n2\frac1 {n+1}\sum_{i=0}^n{(n-i)}=\frac1 {n+1}\frac{n (n+1)} 2=\frac n 2n+11​∑i=0n​(n−i)=n+11​2n(n+1)​=2n​

即就整体性能来说,在插入时有n+1个插入位置,平均移动n2\frac n 22n​个表项!

在删除第i个表项(1≤\leq≤ i ≤\leq≤n)时,必须从前向后循环,逐个移动n一i个表项。 因此,最好的情形是删去最后的第n个表项,移动表项个数为0;最差情形是删去第1个表项,移动项个数为n-1;平均数据移动次数AMN在各表项删除概率相等时为

AMN=1n∑i=1n(n−i)=1nn(n−1)2=n−12\frac1 n\sum_{i=1}^n{(n-i)}=\frac1 {n}\frac{n (n-1)} 2=\frac {n-1} 2n1​∑i=1n​(n−i)=n1​2n(n−1)​=2n−1​

就整体性能来说,在删除时有n个删除位置,平均移动(n-1)/2个表项。

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

C++语言实现顺序表的更多相关文章

  1. C语言实现顺序表

    C语言实现顺序表代码 文件SeqList.cpp #pragma warning(disable: 4715) #include"SeqList.h" void ShowSeqLi ...

  2. C语言实现顺序表(顺序存储结构)

    顺序表(顺序存储结构)及初始化过程详解 顺序表,全名顺序存储结构,是线性表的一种.通过<线性表>一节的学习我们知道,线性表用于存储逻辑关系为"一对一"的数据,顺序表自然 ...

  3. java语言建立顺序表

    package datastructure; //线性表 public interface IList { public void clear(); public boolean isEmpty(); ...

  4. C语言实现顺序表的基本操作(从键盘输入 生成线性表,读txt文件生成线性表和数组生成线性表----三种写法)

    经过三天的时间终于把顺序表的操作实现搞定了.(主要是在测试部分停留了太长时间) 1. 线性表顺序存储的概念:指的是在内存中用一段地址连续的存储单元依次存储线性表中的元素. 2. 采用的实现方式:一段地 ...

  5. c语言实现--顺序表操作

    经过三天的时间终于把顺序表的操作实现搞定了.(主要是在测试部分停留了太长时间) 1;线性表顺序存储的概念:指的是在内存中用一段地址连续的存储单元依次存储线性表中的元素. 2;采用的实现方式:一段地址连 ...

  6. 顺序表及其多种实现方式 --- C/C++

    所谓顺序表,即线性表的顺序存储结构.下面给出的是数据结构---线性表的定义. ADT List{ 数据对象: 线性表的数据对象的集合为{a1,a2,a3,...,an},每个元素的类型为ElemTyp ...

  7. C++实现动态顺序表

    顺序表是在计算机内存中以数组的形式保存的线性表,是指用一组地址连续的存储单元依次存储数据元素的线性结构.这样的存储方式使得线性表逻辑上相邻的元素,其在物理存储单元中也是相邻的.只要知道了第一个元素的存 ...

  8. 动态顺序表(C++实现)

    顺序表是在计算机内存中以数组的形式保存的线性表,是指用一组地址连续的存储单元依次存储数据元素的线性结构. 这样的存储方式使得线性表逻辑上相邻的元素,其在物理存储单元中也是相邻的.只要知道了第一个元素的 ...

  9. 数据结构C语言版--动态顺序表的基本功能实现(二)

    /* * 若各个方法结构体变量参数为: &L(即地址符加变量)则结构体变量访问结构成员变量时使用"." * 若为:*L(即取地址符加变量)则结构体变量访问结构体成员变量使用 ...

随机推荐

  1. 初识Flask、快速启动

    目录 一.初识Flask 1.1 什么是flask? 1.2 为什么要有flask? 二.Flask快速启动 一.初识Flask 1.1 什么是flask? Flask 本是作者 Armin Rona ...

  2. Redis 服务端程序实现原理

    上篇我们简单介绍了 redis 客户端的一些基本概念,包括其 client 数据结构中对应的相关字段的含义,本篇我们结合这些,来分析分析 redis 服务端程序是如何运行的.一条命令请求的完成,客户端 ...

  3. liunx 安装 zookeeper(转)

    转自:https://www.cnblogs.com/expiator/p/9853378.html linux安装zookeeper及使用 一.安装条件 想要安装zookeeper,必须先在linu ...

  4. Scala尾递归

    递归函数应用 首先,我们来对比两个递归方法的求值步骤. 假设有方法gcd,用来计算两个数的最大公约数.下面是欧几里得算法的实现: def gcp(a: Int, b: Int): Int = if ( ...

  5. Lambda表达式学习笔记

    Lambda基础语法 Java8中引入了一个新的操作符" -> ",该操作符被称为箭头操作符或Lambda操作符,箭头操作符将Lambda表达式拆分成两部分: 左侧:Lamb ...

  6. Journal of Proteome Research | “Differential Visual Proteomics”: Enabling the Proteome-Wide Comparison of Protein Structures of Single-Cells(“差异视觉蛋白质组学”:实现单细胞中蛋白质结构的组学比较)(解读人:李思奇)

    期刊名:Journal of Proteome Research 发表时间:(2019年9月) IF:3.78 (2018) 单位:巴塞尔大学,瑞士 物种:人细胞系 技术:冷冻电子显微镜(Cryo-E ...

  7. Red Team 工具集之网络钓鱼和水坑攻击

    来自:信安之路(微信号:xazlsec),作者:myh0st 参考项目:https://github.com/infosecn1nja/Red-Teaming-Toolkit 上图是一个 Red Te ...

  8. C语言学生管理系统

    想练习一下链表,所以就有了这个用C写的学生管理系统 没有把它写入文件,才不是因为我懒哈哈哈,主要是为了练习链表的 #include<stdio.h> #include<stdlib. ...

  9. vue的使用经验

    导读 这一次的口号是,带你重新认识vue,拯救1,2个前端开发者. 从2018年从事前端职业以来,呆过大小公司,干这一行都有2年多.代码写的多了,就越来越体会新手程序员都是挖坑的.在工作过程中,用一种 ...

  10. MySQL的死锁系列- 锁的类型以及加锁原理

    疫情期间在家工作时,同事使用了 insert into on duplicate key update 语句进行插入去重,但是在测试过程中发现了死锁现象: ERROR 1213 (40001): De ...