数据结构C语言版:顺序表基本操作的实现

参考教材:数据结构C语言版(严蔚敏,吴伟民编著)

目录

线性表的基本操作:

1:线性表L的初始化(参数用引用)

2:销毁线性表L

3:清空线性表L

4:求线性表L的长度

5:判断线性表是否为空

6:顺序表的取值(根据位置i获取相应位置数据元素的内容)

7:线性表的查找

8:顺序表的插入 

9:顺序表的删除


线性表的基本操作:

补充:操作算法中用到的预定义常量和类型

//函数结果状态代码
#define    TURE           1
#define    FALSE          0
#define    OK             1
#define    ERROR          0
#define    INFEASIBLE     -1
#define    OVERFLOW       -2
//Status是函数的类型,其值是函数结果状态的代码
typedef  int  Status;
typedef  char  ElemType;

1:线性表L的初始化(参数用引用)

Status InitList_Sq(SqList &L){    //构造一个空的顺序表LL.elem=new ElemType[MAXSIZE];    //为顺序表分配空间if(!L.elem) exit(OVERFLOW);//存储分配失败L.length=0;                //空表长度为0return Ok;
}

new表示动态分配空间,即空间可伸缩

这个函数是初始化线性表,1.给数组分配空间,并检测分配是否成功        2.为长度赋值为0

if(!L.elem):这是一个条件语句,检查线性表L中的elem’成员是否为NULL或者未分配。’!是逻辑非运算符,所以’!L.elem”的意思是如果L.elem'为NULL或者未分配,条件成立。

c的写法是(elem type*)malloc(sizeof(elemtype)*maxsize;

2:销毁线性表L

void DestroyList(SqList &L){if(L.elem) delete L.elem;//释放存储空间
}

 销毁:从内存中将L占用的空间释放

前提条件:有空间才才释放,没有空间不需要释放

if(L.elem) delete L.elem:如果这个线性表存在,然后将他删除掉,线性表L将不再存在。

3:清空线性表L

vold ClearList(SqList &L){L.length=0;    //将线性表的长度置为0
}

这个就属于逻辑上的清空,让之前的数据找不到了就叫做清空。

逻辑清空,假装已经清空了,只要把长度变成0,那么后面的访问超出范围就会主动拒绝掉。

4:求线性表L的长度

int GetLength(SqList L){return (L.length);
}

这里可以加&,这样当列表很大时可以节约开辟副本的时间和空间。

5:判断线性表是否为空

int IsEmpty(SqList L){
if (L.length==0) return 1;
else return 0;
}

if (L.length==0):判断线性表是否为空,如果是空的则返回1,不是空的返回0

6:顺序表的取值(根据位置i获取相应位置数据元素的内容)

int GetElem(SqList L,int i,ElemType &e){if (i<1||i>L.length) return ERROR;//判断i值是否合理,若不合理,返回ERRORe=L.elem[i-1];//第i-1的单元存储着第i个数据return Ok;
}

不引用是因为,不需要修改,牢记一点:是否需要对这个数据进行修改?不需要修改那么不需要引用。

只要记住,引用&的目的是修改这个数据,不修改就不引用,这个要点可以解答你所有有关“为什么&,为什么不&”的问题

i是需要获取第i个元素,e代表要取出的元素,这里用&引用直接会修改传入的变量e

这里i是位序,逻辑位序,物理位序的话是数组的下标,差了1,所以逻辑上的i,实际上是数组里的i-1

判断里是逻辑序号1,2,...,length, e的赋值语句里是物理序号0,1,,...,length-1,也可以把判断换成i<0||i>L.length-1

因为每个语句只执行一次,此处的时间复杂度为常量阶:O(1)

线性表的常用的两种储存结构:顺序存储结构(顺序表)和链式存储结构(链表)

7:线性表的查找

1:在线性表L中查找与指定值e相同的数据元素的位置

2:从表的一端开始,逐个进行记录的关键字和给定值的比较。如果找到,返回该元素的位置序号,未找到,返回0。 

int LocateELem(SqList L, ElemType e){
//在线性表L中查找值为e的数据元素,返回其序号(是第几个元素)for (i=0;i< L.length;i++)if(L.elem[i]==e) return i+1; //查找成功,返回序号return 0; //查找失败,返回0
}

这里面elem如果是自定义类型,是不可以做相等判断的,需要重载==

l.length就是元素的个数,因为下标从0开始,所以i=0,从0开始查找

i是对比数组里下标为i的数,数组的实际使用个数=l.length,但是下标是length-1.

此算法的执行次数最多的语句是: if(L.elem[i]==e) return i+1;         时间复杂度:O(n)

int LocateELem(SqList L, ElemType e){
//在线性表L中查找值为e的数据元素,返回其序号(是第几个元素)while (i< L.length&&L.elem[i]!=e) i++;if(i<L.length) return i+1; //查找成功,返回序号return 0; //查找失败,返回0
}

顺序表的查找分析:

因为查找算法的基本操作为:将记录的关键字同给定值进行比较

基本操作:L.elem[i] == e

比较次数,e=a,1次;e=b,2次;e=c,3次;......,e=g,7次

平均查找次数:(1+2+3+4+5+6+7)/7 =4次        (首相加末项)/2=(1+7)/2

最好情况:查找的元素就在表头,仅需比较一次,时间复杂度为O(1)。
最坏情况:查找的元素在表尾(或不存在)时,需要比较n次,时间复杂度为O(n)

平均查找长度ASL(Average Search Length)

为确定记录在表中的位置,需要与给定值进行比较的关键字的个数的期望值叫做查找算法的平均查找长度。

对含有n个记录的表,查找成功时:

Pi:第i个记录被查找的概率        Ci:找到第i个记录需比较的的次数

顺序查找的平均查找长度:ASL=P_{1}*1+P_{2}*2+...+(n-1)P_{n-1}+nP_{n}

假设每个记录的查找概率相等:P_{i}=\frac{1}{n}

假如P_{1}=P_{2}=...=P_{n}=\frac{1}{n},则ASL=P_{1}*1+P_{2}*2+...+(n-1)P_{n-1}+nP_{n} \\=\frac{1}{n}(1+2+..+n) \\=\frac{1}{n}*\frac{n(n+1)}{2} \\=\frac{n+1}{2}

8:顺序表的插入 

线性表的插入运算是指在表的第 (1≤i<n(L.length)+1)个位置上,插入一个新结点(元素) e,使长度为n(L.length)的线性表(a1,… ai -1,ai,… an)变成长度为n+1(L.length+1) 的线性表(a1, .. ai -1,e, ai,an)。

算法思想:①判断插入位置i 是否合法。
②判断顺序表的存储空间是否已满,若已满返回ERROR。                                                            ③将第n至第ì 位的元素依次向后移动一个位置,空出第i个位置                                                      ④将要插入的新元素e放入第i个位置。                                                                                            ⑤表长加1,插入成功返回OK。

Status ListInsert_Sq(SqList &L,int i ,ElemType e){if(i < 1 || i > L.Length+1)return ERROR;    //i值不合法if(L.length == MAXSIZE) return ERROR;        //当前存储空间已满for(j = L.length-1; j >= i-1; j--)L.elem[j+1]=L.elem[j];                //插入位置及之后的元素后移L.elem[i-1]=e;    //将新元素e放入第i个位置L.length++;            //表长增1return OK;
}

if(i < 1 || i > L.Length+1)return ERROR:判断i的范围是否有效,i只能在1~L.length+1的范围,如果i不在规定范围:i<1或i > L.Length+1,则返回error。注意:这里的i是位序 不是组数下标! 

if(L.length == MAXSIZE) return ERROR:判断当前的存储空间是否已满,L.length == MAXSIZE:当前存储空间已满,不能插入,则返回error

 for(j = L.length-1; j >= i-1; j--)
        L.elem[j+1]=L.elem[j];  
   :j是数组下标,将第i个元素及之后的元素后移,将下标为j的元素放入到j+1

p要小于等于n+1就是只能紧贴着原数组的最后一个元素去插入,因为线性表规定所有元素必须紧挨在一起,不能出现空一个的情况

算法时间主要耗费在移动元素的操作上:
若插入在尾结点之后,则根本无需移动(特别快);        时间复杂度:O(1)

若插入在首结点之前,则表中元素全部后移(特别慢);        时间复杂度:O(n)

若要考虑在各种位置插入(共n+1种可能)的平均移动次数,该如何计算? 

i+x=n+1,x=n+1-i        i是第几个位置,x是移动次数

i~n总共移动x次,也就是总共x个元素,移动后i~n下标变成i+1~n+1,所以前面i个元素与后面x个元素的和为n+1。

i是位序(插到第几位),n是下标,x是移动次数,例:数组有5个元素,把新元素添插在最后就是第6;代入公式:6+0=5+1。

再来一个理解方法:n+1是插入新元素数组的最后一个位置,i是插入元素的位置,移动次数就是[最后-当前]=[n+1-i]

设pi代表在第i个位置上插入一个结点的概率,那么pi=1/(n+1),所以在长度为n个结点的顺序表中插入结点时所需要移动的平均次数可以这样表示·: 

顺序表插入算法的平均时间复杂度:O(n)

插入不同位置的算法演示:

插入位置在最后:

插入位置在中间:

实际操作的时候,  先判断数组是否满, 满就返回错误。然后如果是在中间插入, 当然需要挪元素, 需要挪最后一个元素,最后一个元素的位序是 length-1 , 然后挪到length的位置

插入位置在最前面: 

可以遍历整一个逆序的数组,然后在最后面插入一个元素,然后再遍历逆序一下,回到原来的数组

9:顺序表的删除

线性表的删除运算是指将表的第 i (1 ≤ i ≤ n(L.length) )个结点删除

使长度为n 的线性表(a_{1},...,a_{i-1},a_{i},a_{i+1},...,a_{n})

变成长度为n-1的线性表(a_{1},...,a_{i-1},a_{i+1},...,a_{n})

算法思想:
①判断删除位置i 是否合法(合法值为1≤i≤n)。不合法则返回ERROR                                                  ②将欲删除的元素保留在e中。
③将第i+1至第n 位的元素依次向前移动一个位置。
④表长减1,删除成功返回OK。 

Status ListDelete_Sq(SqList &L,int i){if((i < 1)||(i > L.length)) return ERROR; //i值不合法for (j = i;j <= L.length-1; j+ +)         L.elem[j-1 ]= L.elem[j];               //被删除元素之后的元素前移 L.length- -;                           //表长减1return OK;                           
}

Status ListDelete_Sq(SqList &L,int i):在线性表L上面删除第i个位置上的元素,删除的结果仍由线性表L保存

if((i < 1)||(i > L.length)) return ERROR:判断删除位置是否合法,如果是小于1或大于L.length,则不合法,返回ERROR,位置合法,进行下一步。L.length就是元素的个数。

for (j = i;j <= L.length-1; j+ +)   :从删除的元素i的后继开始,一直到最后一个元素L.length。 L.length个元素在L.length-1的位置存储。

L.elem[j-1 ]= L.elem[j]:将后面一个元素,赋值到前一个位置

i理解为位置,j是下标,i位置是(1~n),j对应下标是(0~n-1),所以删第i个位置就是删下标i-1。这里是j等于i,是指位置序号,不是数组下标

这里包括前面的代码都是删除指定位置的元素而不是指定索引的元素。

算法时间主要耗费在移动元素的操作上:
若删除尾结点,则根本无需移动(特别快);                        时间复杂度:O(1)
若删除首结点,则表中n-1个元素全部前移(特别慢);      时间复杂度:O(n)                                      若要考虑在各种位置删除(共n种可能)的平均移动次数,该如何计算?

 

i=1,2,3,...,n                x(次数)=n-1,n-2,...,0        i和x的关系:n-i

将移动次数相加:((n-1) + (n-2)+...+(0)) / n

顺序表删除算法的平均时间复杂度为O(n) 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/28554.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

比亚迪智驾技术震撼登场!L3级自动驾驶领跑全国,无图导航、夜间挑战轻松应对!

作为新能源汽车领域的翘楚&#xff0c;比亚迪在电池技术与智能驾驶方面都有着卓越的表现。近日&#xff0c;比亚迪凭借其领先的智驾技术&#xff0c;成功入选全国首批L3级自动驾驶上路及行驶试点名单&#xff0c;这无疑将推动智驾技术的普及速度。 你知道吗&#xff1f;比亚迪智…

单目标应用:基于三角拓扑聚合优化算法TTAO的微电网优化(MATLAB代码)

一、微电网模型介绍 微电网多目标优化调度模型简介_vmgpqv-CSDN博客 参考文献&#xff1a; [1]李兴莘,张靖,何宇,等.基于改进粒子群算法的微电网多目标优化调度[J].电力科学与工程, 2021, 37(3):7 二、三角拓扑聚合优化算法求解微电网 2.1算法简介 三角拓扑聚合优化算法&…

如何连接达梦数据库?

连接达梦数据库&#xff08;DM Database&#xff09;可以通过多种方式进行&#xff0c;包括使用 JDBC&#xff08;Java Database Connectivity&#xff09;驱动程序&#xff0c;这是最常见的方式之一。以下是使用 Java 通过 JDBC 连接达梦数据库的详细步骤&#xff1a; 1. 准备…

梦想编织者Luna:COZE从童话绘本到乐章的奇妙转化

前言 Coze是什么&#xff1f; Coze扣子是字节跳动发布的一款AI聊天机器人构建平台&#xff0c;能够快速创建、调试和优化AI聊天机器人的应用程序。只要你有想法&#xff0c;无需有编程经验&#xff0c;都可以用扣子快速、低门槛搭建专属于你的 Chatbot&#xff0c;并一键发布…

gbase8s数据库的逻辑日志、物理日志和两种特殊情形的学习

(一) 日志的介绍 1. 日志的类别 数据库日志主要是分为记录日志、逻辑日志和物理日志。 记录日志&#xff1a;记录日志包括了数据库的报错日志、连接日志、sql执行等信息&#xff0c;这些日志不存储在dbspace上&#xff0c;而是保存在操作系统的文件内逻辑日志和物理日志&…

Kali之metasploit学习

目标&#xff1a;尝试使用metasploit制作一个windows 后门&#xff08;exe文件&#xff09; 一&#xff1a;使用metasploit生成一个exe安装包。 二、将对应的可执行文件放入到目标机 python3 -m http.server 端口号&#xff1a; 模块化启动一个端口。 windows 证书管理工具&…

Python(二)---数据类型与变量、以及运算符

文章目录 前言1.Python程序的构成1.1.代码的组织和缩进1.2.使用\行连接符 2.对象和引用、标识符规则2.1.对象2.2.引用2.3.标识符规则 3.变量和简单赋值语句3.1.变量的声明和赋值3.2.删除变量和垃圾回收机制3.3.常量3.4.链式赋值3.5.系列解包赋值 4.最基本内置数据类型4.1.数字和…

使用了代理IP怎么还会被封?代理IP到底有没有效果

代理IP作为一种网络工具&#xff0c;被广泛应用于各种场景&#xff0c;例如网络爬虫、海外购物、规避地区限制等。然而&#xff0c;很多用户在使用代理IP的过程中却发现自己的账号被封禁&#xff0c;这让他们不禁产生疑问&#xff1a;使用了代理IP怎么还会被封&#xff1f;代理…

芯片验证分享8 —— 代码审查2

大家好&#xff0c;我是谷公子&#xff0c;上节课给大家讲了代码审查中的代码正向检查&#xff0c;今天我们来讲代码审查的其他方法。 今天介绍的检查方法有&#xff1a; 代码反向检查 桌面检查 同行评审 可用性验证 这些验证方法可以应用在芯片开发的任何阶段。代码审查…

《Cloud Native Data Center Networking》(云原生数据中心网络设计)读书笔记 -- 01 为什么需要一个新的网络架构

关于专栏 本专栏是工作之后阅读 Cloud Native Data Center Networking &#xff08; O’Reilly, 2019&#xff09;的读书笔记。这本书是我在数据中心从事云网络工作的启蒙、扫盲读物。可惜&#xff0c;其中文版翻译并非尽善尽美&#xff0c;必须结合英文原版才能理解原作者要表…

第 4 章:从 Spring Framework 到 Spring Boot

通过前面几个章节的介绍&#xff0c;相信大家已经对 Spring Framework 有了一个基本的认识&#xff0c;相比早期那些没有 Spring Framework 加持的项目而言&#xff0c;它让生产力产生了质的飞跃。但人们的追求是无止境的&#xff0c;这也驱动着技术的发展。开发者认为 Spring …

基于SSM+Jsp的列车票务信息管理系统

开发语言&#xff1a;Java框架&#xff1a;ssm技术&#xff1a;JSPJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包…

期末算法复习

0-1背包问题&#xff08;动态规划&#xff09; 例题 算法思想&#xff1a; 动态规划的核心思想是将原问题拆分成若干个子问题&#xff0c;并利用已解决的子问题的解来求解更大规模的问题。 主要是状态转移方程和状态 算法描述&#xff1a; 初始化一个二维数组dp&#xff0…

312. 戳气球

. - 力扣&#xff08;LeetCode&#xff09; 这是区间问题&#xff0c;f[i][j] 是在{nums[i]::nums[j]}的获得的最大零钱数&#xff0c;跟回文字符串的思路差不多。 方法一&#xff1a; i ∈{0:: n-1} 从左往右来看。 class Solution { public:int maxCoins(vector<int>…

【计算机毕业设计】259基于微信小程序的医院综合服务平台

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

禁止methtype联网

mathtype断网_如何禁止mathtype联网-CSDN博客https://blog.csdn.net/qq_41060221/article/details/128144783

【猫狗分类】Pytorch VGG16 实现猫狗分类5-预测新图片

背景 好了&#xff0c;现在开尝试预测新的图片&#xff0c;并且让vgg16模型判断是狗还是猫吧。 声明&#xff1a;整个数据和代码来自于b站&#xff0c;链接&#xff1a;使用pytorch框架手把手教你利用VGG16网络编写猫狗分类程序_哔哩哔哩_bilibili 预测 1、导包 from to…

没有名为 keras.preprocessing 的模块

估计是因为版本原因 我安装的是 3.3.3版本 >>> import keras >>> print(keras.__version__) 3.3.3 keras.preprocessing.image 只需要将 keras.preprocessing.image 改为 from keras_preprocessing.image 即可

Spring高手之路20——深入理解@EnableAspectJAutoProxy的力量

文章目录 1. 初始调试代码2. 源码跟踪分析2.1 初探EnableAspectJAutoProxy2.2 registerBeanDefinitions方法和时序图分析2.3 registerOrEscalateApcAsRequired方法和时序图分析 1. 初始调试代码 面向切面编程&#xff08;AOP&#xff09;是一种编程范式&#xff0c;用于增强软件…

异常向量表的设置

1、Linux Kernel中对异常向量表的填充 linux/arch/arm64/kernel/entry.S kernel_ventry 是一个定义异常向量的宏&#xff1b; 在该宏中&#xff0c;程序跳转到了b el\el\ht()\regsize()\label; 以为异常向量的第6行为例&#xff0c;其实就是跳转到了bl el1h_64_irq; 然后你去搜…