数据结构(2)线性表-顺序表

知道一个算法的好坏怎么去判断以后,就该正式的去学习一些常见的数据结构,当然,这里的数据结构仅仅是初阶,不会挨个一个一个学完,后期慢慢来。

一、数据结构总论

一般按照逻辑结构和存储结构来分类,在初阶的学习时,虽不能全部学完,但基本每个类别都能见到例子。

1.按逻辑结构分类

按照逻辑结构分类,可以分为集合结构(数据元素同属于一个集合,但是并没有任何的关系)、线性结构(数据元素一对一,好像一条线一样连在了一起)、树形结构(数据元素一对多的关系,就好像一个树的主干的根只有一个,但是他身上每一个节点都可能有好几个树枝)、图状/网状结构(这种结构就类似于在天上俯瞰一个城市的公路一样,每条路的十字看做一个数据元素的话,那就是多对多的关系)

2.按存储结构分类

按照存储结构有顺序存储(如数组,数组元素就是在内存中连续的存储)、链式存储(其实在C语言学习结构体的时候我们就已经见过怎样建立一个链表节点,即一个数据域,一个地址,这个地址是指向链式存储的下一个数据元素)、索引存储、哈希存储(根据散列函数的计算而定位数据元素)。

二、线性表

线性表是一类数据结构的总称,这一类数据结构最明显的特点就是逻辑上是线性的,但是物理上不一定是线性的。

也就是说,线性表在使用的时候,在我们的大脑中思考就是连续的、线性的,但实际上在内存中的存储可不一定是顺序存储。

三、顺序表

1.概述

这次学习的顺序表就是属于线性表,符合线性表的特征,即逻辑结构是线性结构,且数据顺序存储(底层实现类似于数组,或者说借助于数组)。

2.顺序表和数组的区别

这个时候就有人要问了,既然你跟我说顺序表借助于数组实现,那为啥不就当成数组呢。它们两个的关系就类似于什么呢:
我相信基本上能跟编程打交道的,你说你自己一点也不玩游戏,我是不信的,甭管玩手机游戏还是电脑游戏,你要玩游戏最基本得有个设备吧,就说手机游戏,你弄个平板玩,正常就搂着玩就行了呗,但是有的人嫌举着累,买个支架,又嫌自己打游戏的时候发热会导致掉帧,卡的不行,又买了一个散热器,手老出汗买个指套,更有甚者玩个手机游戏开加速器。

顺序表和数组基本就是这样的,数组只能存一系列数据,你存着只能取出来用,对里面的数据进行增删改是很麻烦的,顺序表在创建好以后,相当于数组+增加/删除/修改/查找……一系列的辅助工具,帮助你对数据进行维护,数组就没有这个条件。

3.顺序表的声明

①静态顺序表

静态数据表就是用定长数组来存储数据的,当然,并不等同于数组,一般都是这样定义的:

#define定义是为了方便修改静态顺序表的大小,即底层的数组的大小,为什么要将数组的类型由typedef定义一下呢,直接写个int不行吗?

给顺序表的数据的类型取别名也是为了方便修改顺序表所存储的数据类型。

这样看来顺序表也没比数组好到哪去,只不过可以确定有效数据个数而已。

这么看当然看不出来顺序表相对于数组的优点,因为正常情况下,比如用顺序表来存储双11某用户的订单个数,这种玩意肯定是动态的,不能说你就给他7个大小的内存,假如就说成7个订单,那万一双十一买的多了咋办,难道还能让用户少买一点吗?肯定是用户创建的订单决定数据存储的大小,也就是经常用的就是动态顺序表。

②动态顺序表

动态和静态的区别在哪里那,其实举的小例子已经给出了,静态的顺序表存储的数据个数是固定的,你给少了吧就不够用,给多了吧,又给内存浪费了(不要小看内存浪费,一个人浪费1000个字节,人多起来再多的内存都不够用)。

千万不要说,那你说要多大,比如存7个int,我就给你#define N 7,你要几我就定义几,这真就是对程序的内存申请不了解啊,在C语言学习的时候不说别的,编译的时候就给这个顺序表的内存大小固定死了,你把N定义的值改了有什么用,你程序已经写好了,软件里就是这么大,你说改成9,那么软件就不能用了,就得重新把你改好的应用到软件里,你敢想象双十一,特别是双十一的晚上购物平台提交不了订单会造成多大的损失吗,等你改好再上架,黄花菜都凉了。

因此,来看我们动态顺序表的声明(动态就是可以根据你给的数据,去调整申请的内存大小)。

因为要动态申请,所以提前准备一个指针,去接收不管是malloc还是calloc等去申请的那块内存空间的地址,有效数据个数不用多说,而静态顺序表的大小是确定的,动态顺序表只能动态计算去确定,因此多加一个capacity变量。

4.动态顺序表的初始化

声明好一个变量做的第一件事就是初始化,创建一个顺序表也是如此:

信心满满的写完了,然后:

???

你这破计算机犯什么毛病,我已经第六行就是给你初始化去的,你告诉我未初始化干嘛。

其实还是我们之前提过的一个问题,传值调用和传址调用。

传值调用只是对实参的一个临时拷贝,如果仅仅用于计算,无可厚非,但是如果想传值用形参来实现修改实参的话,那还是想想算了。

形参的值不影响实参的值,出了函数还直接没了。

如果相对实参进行修改,那还是传地址过来吧,让我顺着地址给你修改:

又再次复习了一下,这次可就是传值传址调用的实例了,不再是空泛的硬憋出来的例子。

5.顺序表的插入

尾插

比如这样的数据:

想在尾部插入的话得有size吧,知道了size才能知道该插入的位置(即我们想象出来的下标),这块内存空间的起始地址也得有吧,因此,干脆直接像初始化一样,传过来这个顺序表的地址,你想去用这个顺序表哪个成员就用哪个成员,最后另外写出来一个参数,这个参数接收需要插入的元素:

当然,这么写就是错的,顺序表只初始化是没有对应的内存空间的,并没有给这个顺序表申请空间,是不能去赋值的,所以在此之前先怼一个内存开辟,由于考虑到内存可能溢出的问题,所以malloc calloc realloc用realloc,这样如果第一次开辟的内存不够用,可以自主开辟:

realloc第一个参数如果是NULL的话,效果和malloc是一样的,因为需要修改的位置为空,那么就不需要修改,直接开辟即可,返回值仍需检查。

调试结果就是这样的,其实挺简单的。

头插

这个有两个要注意的点,一个是头插必须把已有的数据后移,空出来顺序表最前面的位置;后移必后面的先移,不然就会导致数据的覆盖:

最后空出来的赋值就简单了,下面是代码表达:

调试没问题:

指定位置插入

其实如果空想的话,你给我的下标是几,那我就把这个下标开始加上后面的全部都后移,最后在这个位置插入你想插的元素:

真是服了,写出来一大堆乱码,检查了半天是因为自己在扩容的时候写错了:

我算出来的newcapacity是元素个数,人家realloc要的是字节数,还得乘一下,调试半天。

其它没什么疑问:

6.顺序表的删除

尾删

直接给出

删除操作,下意识的我们就可能想到,必须把尾部的数据给删除了,但是实际上删除以后难道计算机对于这块位置就不再管了吗?显然不是的,只是变成乱码了而已,假设给上乱码,你不还是得size--嘛,反正也就是为了不再访问顺序表尾部的值,直接size--即可

头删

从前往后覆盖即可:

比如这个,就是从2->1,3->2等等即可。

代码表达:

测试:

一样道理,即使最后的不删,size为3,不管你做遍历还是插入等一系列操作,都不会被这个值影响。

指定位置删除

类似于头插的前移,只不过与所给位置有关而已:

调试:

7.顺序表的查找

参数肯定是一个顺序表,一个需要查找的元素,不过这次仅仅是查找,可以传值调用了,毕竟不要求对数据源进行修改,仅仅是对比。

调试:

8.顺序表遍历打印

当然,这里只写int类型的遍历:

调试:

毋庸置疑。

9.顺序表的销毁

如果你写的是局部变量,那就等出了函数系统自动回收空间就算了,但是我们用的最多的是动态顺序表,也就意味着有一块动态开辟的内存空间,碰见这样的事的话,用完了手动给它回收吧,不过我们要给它封装成一个函数:

不用多解释,其实就是调用了个free,最后置指针为空。

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

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

相关文章

性能测试详解

🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 一、什么是性能测试 先看下百度百科对它的定义 性能测试是通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试 我们可以认为…

每日Prompt:三只动物与地标自拍磨砂玻璃后的虚实对比剪影

提示词 一张黑白照片,展示了一个[主体]在磨砂或半透明表面后的模糊剪影。其[部分]轮廓清晰,紧贴表面,与其余朦胧、模糊的身影形成鲜明对比。背景是柔和的灰色渐变色调,增强了神秘和艺术的氛围。

Android多媒体——媒体解码器初始化(十五)

通过上一篇文章我们了解了媒体解码器的创建过程,并且可以看到,在媒体解码器创建成功后,分别调用了 configure()、setCallback() 和 start() 函数来对解码器进行配置、回调和启动。这里我们就来详细看一下这几个过程。 一、配置解码器 首先看一下解码器的配置,在 NuPlayerD…

每周资讯 | 腾讯Q1财报:国内游戏业务收入同比增长24%;Tripledot 8亿美元收购AppLovin游戏业务

内容速览: 广州“服务贸易和数字贸易22条”助推游戏产业发展Tripledot Studios 8亿美元收购AppLovin游戏业务苹果紧急申请暂停执行AppStore新规4月中国手游出海收入下载榜,点点互动《Kingshot》收入激增 腾讯Q1财报:国内游戏业务收入同比增长…

本地跑通vue-element-admin项目

GitHub - PanJiaChen/vue-element-admin: :tada: A magical vue admin https://panjiachen.github.io/vue-element-admin 通过加速clone到本地 git clone https://gitclone.com/github.com/PanJiaChen/vue-element-admin.git # 进入项目目录 cd vue-element-admin # 安装依赖…

Go语言交替打印问题及多种实现方法

Go语言交替打印问题及多种实现方法 在并发编程中,多个线程(或 goroutine)交替执行任务是一个经典问题。本文将以 Go 语言为例,介绍如何实现多个 goroutine 交替打印数字的功能,并展示几种不同的实现方法。 Go 语言相关…

支持蓝牙5.0和2.4G私有协议芯片-PHY6222

PHY6222QC-W04C 是一款适用于蓝牙低功耗(BLE)5.2 应用的片上系统(SoC)。它搭载 ARM Cortex™-M0 32 位处理器,配备 64KB SRAM、512K Flash、96KB ROM、256 bit efuse ,以及超低功耗、高性能的多模式射频模块…

git相关配置

git相关配置 欢迎使用Markdown编辑器修改Git默认编辑器为vimgit配置默认用户名和密码: 欢迎使用Markdown编辑器 修改Git默认编辑器为vim #方法1:直接执行 git config --global core.editor vim#方法2:修改git的配置文件.git/config文件&am…

C语言实现INI配置文件读取和写入

一.INI文件介绍 INI配置文件是一种简单的文本文件,用于存储配置信息,通常由一个或多个节(section)组成,每个节包含多个键值对(Key-Value)格式。INI文件易于阅读和编辑,广泛应用于多…

Vue 3 打开 el-dialog 时使 el-input 获取焦点

运行代码:https://andi.cn/page/622178.html 效果:

【程序员AI入门:模型】19.开源模型工程化全攻略:从选型部署到高效集成,LangChain与One-API双剑合璧

一、模型选型与验证:精准匹配业务需求 (一)多维度评估体系 通过量化指标权重实现科学选型,示例代码计算模型综合得分: # 评估指标权重与模型得分 requirements {"accuracy": 0.4, "latency": …

卡顿检测与 Choreographer 原理

一、卡顿检测的原理 卡顿的本质是主线程(UI 线程)未能及时完成某帧的渲染任务(超过 16.6ms,以 60Hz 屏幕为例),导致丢帧(Frame Drop)。检测卡顿的核心思路是监控主线程任务的执行时…

物联网僵尸网络防御:从设备认证到流量染色

一、IoT设备的安全困境 典型物联网设备存在硬编码密钥问题: // 固件中的危险代码示例 const char* DEFAULT_KEY "A1B2-C3D4-E5F6"; // 厂商预设密钥 void connect_server() {authenticate(DEFAULT_KEY); // 密钥从未更新 }此类漏洞导致某智能家居平台…

二叉树子树判断:从递归到迭代的全方位解析

一、题目解析 题目描述 给定两棵二叉树root和subRoot,判断root中是否存在一棵子树,其结构和节点值与subRoot完全相同。 示例说明 示例1: root [3,4,5,1,2],subRoot [4,1,2] 返回true,因为root的左子树与subRoot完…

Springboot 异步场景 使用注解 @Async 及 自定义线程池分模块使用

目录 前言一、Springboot项目如何开启异步?二、存在的问题三、自定义线程池四、自定义线程池使用五、阻塞队列和拒绝策略 前言 当开发中遇到不影响主流程任务时,使用异步去处理。 如有以下场景: 1、业务需要生成一个季度的数据进行员工排名&…

【GNN笔记】Signed Graph Convolutional Network(12)【未完】

视频链接:《图神经网络》 Signed Graph Convolutional Network 之前介绍的GNN模型主要集中在无符号的网络(或仅由正链接组成的图)上,符号 图带来的挑战,主要集中在于 否定链接,与正链接相比,它不…

米勒电容补偿的理解

米勒电容补偿是使运放放大器稳定的重要手法,可以使两级运放的两个极点分离,从而可以得到更好的相位裕度。 Miller 电容补偿的本质是增加一条通路流电流,流电流才是miller效应的本质。给定一个相同的输入,Miller 电容吃掉的电流比…

CVE-2017-8046 漏洞深度分析

漏洞概述 CVE-2017-8046 是 Spring Data REST 框架中的一个高危远程代码执行漏洞&#xff0c;影响版本包括 Spring Data REST < 2.5.12、2.6.7、3.0 RC3 及关联的 Spring Boot 和 Spring Data 旧版本。攻击者通过构造包含恶意 SpEL&#xff08;Spring Expression Language&…

qt文本边框设置

// 计算文本的大致尺寸 QFontMetrics fm(textEditor->font()); QRect textRect fm.boundingRect(textItem->toPlainText()); // 设置编辑框大小&#xff0c;增加一些边距 const int margin 10; textEditor->setGeometry( center.x() - textRect.width()/2 - margin,…

Java 与 面向对象编程(OOP)

Java 是典型的纯面向对象编程语言&#xff08;Pure Object-Oriented Language&#xff09;&#xff0c;其设计严格遵循面向对象&#xff08;OOP&#xff09;的核心原则。以下是具体分析&#xff1a; 1. Java 的面向对象核心特性 (1) 一切皆对象 Java 中几乎所有的操作都围绕…