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

news2024/11/26 0:32:57

参考教材:数据结构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){    //构造一个空的顺序表L
    L.elem=new ElemType[MAXSIZE];    //为顺序表分配空间
    if(!L.elem) exit(OVERFLOW);//存储分配失败
    L.length=0;                //空表长度为0
    return 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值是否合理,若不合理,返回ERROR
    e=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++;            //表长增1
    return 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- -;                           //表长减1
    return 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.coloradmin.cn/o/1827439.html

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

相关文章

⌈ 传知代码 ⌋【算法】实体关系抽取

&#x1f49b;前情提要&#x1f49b; 本文是传知代码平台中的相关前沿知识与技术的分享~ 接下来我们即将进入一个全新的空间&#xff0c;对技术有一个全新的视角~ 本文所涉及所有资源均在传知代码平台可获取 以下的内容一定会让你对AI 赋能时代有一个颠覆性的认识哦&#x…

【内存管理之堆内存】

1.栈上的基元 2.栈上的聚合对象 3.手动分配和释放 4.分配堆内存 5.数组内存分配和释放 6.数组内存分配 7.不要使用野指针 8.黑暗时代

Windows如何找回永久删除的文件?完整教程看完即会!

可以找回永久删除的文件&#xff1f; 你是否也在Windows 10中永久删除过文件&#xff1f;什么是永久删除&#xff1f;通常有5种方法可以永久删除文件&#xff1a; 正常删除文件&#xff0c;然后在回收站中再次删除。使用命令提示符&#xff1a;“del”删除文件。使用“ShiftD…

【设计文档】软件项目详细设计说明书案例(套用模板Word)

1引言 1.1编写目的 1.2项目背景 1.3参考材料 2系统总体设计 2.1整体架构 2.2整体功能架构 2.3整体技术架构 2.4设计目标 2.5.1总体原则 2.5.2实用性和先进性 2.5.3标准化、开放性、兼容性 2.5.4高可靠性、稳定性 2.5.5易用性 2.5.6灵活性和可扩展性 2.5.7经济性和投资保护 3系统…

【PL理论】(26) 内存管理:C语言实现内存管理的方式 | 栈帧的分配和释放 | C/C++ 手动内存管理

&#x1f4ad; 写在前面&#xff1a;在前面的章节中&#xff0c;语言的语义只分配了新的内存位置&#xff0c;我们没有讨论内存位置的释放。在实际的语言中&#xff0c;内存位置在执行过程中会被不断地分配和释放。下面的章节&#xff0c;我们将讨论编程语言的这种内存管理&…

[大模型]XVERSE-7B-chat WebDemo 部署

XVERSE-7B-Chat为XVERSE-7B模型对齐后的版本。 XVERSE-7B 是由深圳元象科技自主研发的支持多语言的大语言模型&#xff08;Large Language Model&#xff09;&#xff0c;参数规模为 70 亿&#xff0c;主要特点如下&#xff1a; 模型结构&#xff1a;XVERSE-7B 使用主流 Deco…

【虚幻5】自学纯蓝图笔记(一)

本笔记使用v15.17.1版本的IDE &#xff0c;v5.4.2的引擎 有许多小的功能记录在快捷键一节中&#xff0c;节省时间就不单独记录 学习本章内容时的机器太差了&#xff0c;i58代的CPU&#xff0c;16g运存&#xff0c;所以GIF截图会非常卡顿 指导老师&#xff1a; B站UP主-张亮002 …

C学习自学笔记

C学习笔记 0>C语言概述 为什么学习C语言 1&#xff09;C的起源和发展------了解即可 B语言、C语言、C语言的产生地&#xff1a;都出自 美国贝尔实验室 2&#xff09;C的特点 优点&#xff1a;代码量小、速度快、功能强大 缺点&#xff1a;危险性高、开发周期长、可移植性…

Linux--MQTT(二)通信基本原理

一、MQTT 通信基本原理 MQTT 是一种基于 客户端 - 服务端 架构的消息传输协议&#xff0c;所以在 MQTT 协议通信中&#xff0c;有两个最为重要的角色&#xff0c;它们便是服务端 和 客户端 。 举例&#xff1a;若开发板向“芯片温度”这一主题发布消息&#xff0c;那么服务…

【Better Lighting V2】Blender商城10周年免费送插件灯光预设和图案轮库场景打光和模拟光透过图案水滴波纹效果

Blender商城10周年免费送插件&#xff1a;https://blendermarket.com/birthday Better Lighting V2 灯光预设和图案轮库 模拟各种环境下光线透过物体效果 各种预设快速调整 非常简单和快速打光调色 更多详细介绍&#xff1a;https://blendermarket.com/products/bette…

前端老古董execCommand——操作 选中文本 样式

文章目录 ⭐前言⭐exe command api用法&#x1f496; example示例&#x1f496; 测试效果 ⭐execommand和getSelection 的联系⭐总结⭐结束 ⭐前言 大家好&#xff0c;我是yma16&#xff0c;本文分享关于 前端老古董execCommand——操作选中文本。 execommand 当一个 HTML 文…

Spring的事务步骤

一、事务处理方案&#xff1a; Spring框架中提供的事务处理方案&#xff1a;一共有两种&#xff1a; 适合中小项目使用的&#xff0c; 注解方案&#xff1a; 注解的方式做事务用起来简单&#xff0c;灵活&#xff0c;方便&#xff0c;中小型项目中用它比较方便&#xff0c;因…

关于二分法的理解(以JS为例)

算法介绍 基本概念 二分查找算法&#xff0c;又称折半查找算法&#xff0c;是一种在有序数组中查找特定元素的高效方法。它的核心思想是将数组分成两半&#xff0c;然后根据目标值与中间元素的比较结果来决定是继续在左半部分还是右半部分进行搜索。 工作原理 初始化&#…

编译安装qemu-devel @FreeBSD

缘起 使用cbsd创建riscv jail的时候提示&#xff1a; you have no qemu-user, please install qemu-devle with BSD_USER and STATIC ops (emulators/qemu-devel) 使用pkg安装之后&#xff0c;创建的riscv jail启动报错&#xff1a; Starting jail: fbriscv, parallel timeo…

【猫狗分类】Pytorch VGG16 实现猫狗分类2-模型构建

背景 数据处理做好了&#xff0c;现在搭建网络 声明&#xff1a;整个数据和代码来自于b站&#xff0c;链接&#xff1a;使用pytorch框架手把手教你利用VGG16网络编写猫狗分类程序_哔哩哔哩_bilibili 我做了复现&#xff0c;并且记录了自己在做这个项目分类时候&#xff0c;一…

【回文 马拉车】214. 最短回文串

本文涉及知识点 回文 马拉车 LeetCode214. 最短回文串 给定一个字符串 s&#xff0c;你可以通过在字符串前面添加字符将其转换为回文串。找到并返回可以用这种方式转换的最短回文串。 示例 1&#xff1a; 输入&#xff1a;s “aacecaaa” 输出&#xff1a;“aaacecaaa” 示…

string类的使用手册

1.构造函数 补充&#xff1a;npos&#xff1a;size_t类型数据的最大值 default (1) string(); 构造空的string类对象 copy (2) string (const string& str); 拷贝构造函数&#xff08;深拷贝&#xff09; substring (3) string (const string& str, size_t pos, size_…

python 实现各种数据分析方法

1、相关性分析 1.1、https://zhuanlan.zhihu.com/p/669355778https://zhuanlan.zhihu.com/p/669355778

【AI学习】Together AI的新研究:Together MoA(Mixture of Agents)

第一次听说Mixture of Agents&#xff0c;原来Agent也能混合&#xff0c;有意思&#xff01; 介绍 Together AI的最新研究“Together MoA”&#xff08;Mixture of Agents&#xff0c;代理混合&#xff09;是一种创新的方法&#xff0c;旨在通过结合多个开源大型语言模型&…

Postman使用教程(Postman详细图文教程)

本文讲解的是postman工具安装、postman安装教程、postman工具下载、postman使用教程。Postman使得得开发人员和测试人员能够更高效地与Web服务进行交互和调试。 Postman不仅支持常见的HTTP方法&#xff0c;如GET、POST、PUT、DELETE等&#xff0c;还提供了丰富的请求编辑功能&…