【数据结构】---顺序表的实现
最近学校开始学习数据结构了,没事就手搓一个顺序表。
🌈线性表
线性表是n个具有相同特性的数据元素的有限序列,是一种实际中广泛使用的数据结构,常见的线性表有顺序表、链表、栈、队列、字符串。
线性表在逻辑上是线性结构,即连续的一条直线,但在物理上不一定连续,线性表在物理上存储时,通常以数组和链式结构的形式存储。
1.1啥是顺序表?
顺序表是在计算机内存中以数组的形式保存的线性表,线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素、使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系,采用顺序存储结构的线性表通常称为顺序表。顺序表是将表中的结点依次存放在计算机内存中一组地址连续的存储单元中。
1.2顺序表和数组的区别
两者的区别主要有:
1.顺序表可以实现动态增长,而普通数组的长度是固定的
2顺序表要求插入的数据在内存中是连续的,普通数组的数据存放可以不连续。
🌈顺序表功能实现:
2.1初始化顺序表SLInit()
在实现初始化之前,我们先来创建一个顺序表类型,其中包括顺序表起始位置的指针,容量,数据个数。
静态顺序表类型:
#define N 100
typedef int SLDateType;
//类型命名//静态顺序表--N太小可能不够用
struct Seqlist
{//int a[N];//以后我不想用int类型的a[]SLDateType a[N];int sz;
};
这个的致命缺点就是如果说存储的数据多,而N小的话就不行了,一般写线性表都是用动态版的。
动态顺序表类型:
#define N 100
typedef int SLDateType;typedef struct SeqList
{SLDateType* a; //记录顺序表的起始位置int capacity; //顺序表的容量int size; //记录顺序表中的数据个数
}SL;
typedef为C语言的关键字,作用是为一种数据类型定义一个新名字
初始化函数SLInit():
void SLInit(SL* ps)
{assert(ps); //判断是否为空,如果是空就不再进行了ps->a = NULL; //指针赋值为空ps->capacity = ps->size = 0; //整形赋值为0
}
上面的SL* ps之所以用到指针,就是因为在进行初始化的时候需要将模板也一并改掉。所以用指针找到原来的地址来改变模板。

2.2销毁顺序表SLDestory()
因为顺序表所用的内存空间是动态开辟在堆区的,所以我们在使用完后需要及时对其进行释放,避免造成内存泄漏。
void SLDestory(SL* ps)
{assert(ps); //断言,如果顺序表是空,就不在销毁了free(ps->a); //这一步最为关键 ,把指针释放掉ps->a = NULL; //指针赋值为空ps->capacity = ps->size = 0; //整形赋值为0
}
其实销毁和初始化基本大差不差,最关键的一点就是销毁时有一个free来释放指针。
assert的好处
我们在其中运用到了assert函数,它包含在assert.h头文件中。
assert的好处就是判空,如果一个顺序表是空的,那就不需要进行初始化,和销毁,如果调用这两个函数就直接报错。可以让我们更快的找到漏洞。
2.3打印顺序表SLPrint()
需要打印的个数就是size的大小,然后一个for循环就可以了。
void SLPrint(SL* ps)
{assert(ps != NULL);for (int i = 0; i < ps->size; i++){printf("%d-", ps->a[i]);}printf("\n");
}
2.4顺序表的容量检查SLCheckCapacity()
检查顺序表的容量是否够用是顺序表的一个很关键的问题。其实检查容量的大小很好检查的,只要判断size和capacity的大小就可以了。
如果capacity>size,就说明顺序表还没有存满。
如果capacity=size,就说明需要扩容了。
void SLCheckCapacity(SL* ps)
{if (ps->capacity == ps->size) //需要扩容了{ //先扩容int newCapacity = ps->capacity == 0 ? 4 : 2 *ps->capacity; //1//再让指针指向这块空间SLDateType* tmp = (SLDateType*)realloc(ps->a, newCapacity * sizeof(SLDateType));if (tmp == NULL) {//如果扩容后的容量还是空,直接报错printf("realloc fail\n");exit(-1);} ps->a = tmp; //3ps->capacity = newCapacity;}
}
这里面1中的代码可能有些不好理解,它的意思是如果说capacity是0的话,就给他4个空间,如果不是0,就把它的空间扩大2倍,然后复制给newCapacity。
2中的代码是新建一个指针,这个指针的目的是让原来的指针指向新开辟的空间。
接下来就该实现重点功能了。
🌈顺序表的增删实现
3.尾插功能SLPushBack()
尾插就是在顺序表的表尾插入数据,所以第一步是先判断顺序表的容量大小。容量不够就扩容。
//尾插
void SLPushBack(SL* ps, SLDateType x)
{//检查容量空间SLCheckCapacity(ps);ps->a[ps->size] = x;ps->size++;
}
之所以有两个参数,这两个参数中,参数1代表的是顺序表,参数2代表的是要插入的数。
4.头插功能SLPushFront()
要想在顺序表的表头插入数据,那么就需要先将顺序表原有的数据从后往前依次向后挪动一位,最后再将数据插入表头。
头插成功的前提是顺序表还有空间可供插入。所以第一步就是检查容量。容量够就进行插入操作。
//头插
void SLPushFront(SL* ps, SLDateType x)
{//检查容量SLCheckCapacity(ps);int end = ps->size - 1; //size-1代表的就是顺序表存储的最后一个数while (end >= 0){ps->a[end + 1] = ps->a[end];--end;}ps->a[0] = x;ps->size++;
}
就是把顺序表往后挪一位,然后把第一位插入x就行了。

5.尾删功能SLPopBack()
尾删就是把最末尾数据给干掉,但是其实仔细想一下,直接把顺序表元素个数-1就行了。
//尾删
void SLPopBack(SL* ps)
{assert(ps->size > 0);//顺序表不为空才可以进行尾删,否则直接报错ps->size--;
}
6.头删功能SLPopFront()
头删功能和头插正好相反,头删是往前覆盖。
//头删
void SLPopFront(SL* ps)
{assert(ps->size > 0);int begin = 1; //数据最起码是一个,不是空顺序表while (begin < ps->size){ps->a[begin - 1] = ps->a[begin];begin++;}ps->size--; //数据减少一个
}

出现多删情况:
如果说把顺序表删成空后还继续删除,那会出现啥情况?

这个就会报错,之所以能检查出来错误就是上面咱们写的断言判断出来的。
其实这几种情况用到的不很多,最多的就是任意位置的插入删除操作。
🌈任意位置的插入删除
7.任意位置(pos)插入
这个pos是位置英文的缩写,在任意位置,我们首先就要指定位置pos.所以又加入一个形参。然后后移pos后面的数据。
对于这个插入来说,我们要进行两次断言:
首先·顺序表不为空,其次:指定的位置在顺序表中,不能小于0,不能大于size。
接下来就是往后移动。
//某位置插入
void SLInsert(SL * ps, int pos, SLDateType x)
{//先防止越界SLCheckCapacity(ps);assert(ps);assert(pos >= 0 && pos <= ps->size);//加上=,可实现尾插int end = ps->size - 1;//从后往前while (end >= pos){ps->a[end + 1] = ps->a[end];--end;}ps->a[pos] = x;ps->size++;
}
8.任意位置(pos)删除
这个跟前面的没事两样,就是加一个形参pos,然后把pos以后的数往前移动。
//某位置删除
void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);//不能等于int begin = pos;for (begin = pos; begin < ps->size - 1; begin++){ps->a[begin] = ps->a[begin + 1];}ps->size--;
}

🌈查改功能的实现
写到这一步,顺序表基本就写完了,只剩下几个功能了。
9.查找功能实现SLfind()
要想实现查找功能,还需要两个形参,但是第二个形参是操作者查找的对象,比如我要去顺序表中查找2,那第二个形参就是2。
如果找到就返回该数字,没找到返回-1.
//查找
int SLFind(SL* ps, SLDateType x)
{assert(ps);for (int i = 0; i < ps->size; i++){if (ps->a[i] == x)return i;}return -1;//没找到
}
10.修改功能SLModify()
//修改
int SLModify(SL* ps, int pos, SLDateType x)
{assert(ps);assert(pos >= 0 && pos < ps->size);ps->a[pos] = x;
}
这里直接在pos位置上修改就行了。
🌈总结:
到这顺序表的大致功能函数就解决完了,但是还是要说一个问题--》
为啥第一个参数要用指针?
形参是实参的一份临时拷贝,修改功能函数里的形参并不会改变实参的任何数据。
就好比你去复印户口簿,复印完发现复印件的地址错了,你如果说你只改复印件上的,那下一次复印地址还是错的。所以必须要通过复印件连着户口本上的一起改成正确地址才行。
这个用指针就是上面的意思,要想改变顺序表中的数据,就要通过指针把顺序表上的内容一起改变。
上面的打印函数就可以不要指针,但是为了更准确和一致,把它也带上把。
相关文章:

【数据结构】---顺序表的实现
最近学校开始学习数据结构了,没事就手搓一个顺序表。🌈线性表线性表是n个具有相同特性的数据元素的有限序列,是一种实际中广泛使用的数据结构,常见的线性表有顺序表、链表、栈、队列、字符串。线性表在逻辑上是线性结构࿰…...
JavaScript刷LeetCode拿offer-经典高频40题vaScript刷LeetCode拿offer-经典高频40题
工作太忙没有时间刷算法题,面试的时候好心虚。这里双手奉上40道LeetCode上经典面试算法题,整理的内容有点长,建议先收藏,慢慢消化,在来年顺利拿到满意的offer。 1、[LeetCode] 两数之和 给定一个整数数组和一个目标值…...

动态规划,这将是你见过最详细的讲解
文章目录一、为什么要讲动态规划呢?二、什么是动态规划三、感受一下递归算法、备忘录算法、动态规划递归算法带备忘录的递归解法(自定向下)自底向上的动态规划四、动态规划的解题套路1. 穷举分析2. 确定边界3. 确定最优子结构4. 写出状态转移…...

【服务器数据恢复】FreeNAS层UFS2文件系统数据恢复案例
服务器数据恢复环境: Dell存储服务器,采用esxi虚拟化系统,esxi虚拟化系统里有3台虚拟机;上层iSCSI使用FreeNAS构建,通过iSCSI方式实现FCSAN功能;FreeNAS层采用UFS2文件系统。 esxi虚拟化系统里有3台虚拟机中…...

Zookeeper安装和基本使用
目录标题一、下载二、安装三、启动客户端测试四、使用zk一、下载 注意:自zk3.5.5版本以后,已编译的jar包,尾部有bin,应该使用的是apache-zookeeper-3.8.0-bin.tar.gz。,因此在下载高版本时,因该下载后缀带b…...

字节面试惨败,闭关修炼再战美团(Android 面经~)
作者:王旭 前言 本人从事Android 开发已经有5年了,受末日寒气影响,被迫在家休整,事后第一家选择字节跳动面试,无奈的被面试官虐得“体无完肤”,好在自己并未气馁,于是回家开始回家进行闭关修炼…...

【机器学习实战】七、梯度下降
梯度下降 一、线性回归 线性回归算法推导过程可以基于最小二乘法直接求解,但这并不是机器学习的思想,由此引入了梯度下降方法。本文讲解其中每一步流程与实验对比分析。 1.初始化 import numpy as np import os %matplotlib inline import matplotli…...

什么是极速文件传输,极速文件传输如何进行大文件传输
当谈到大文件传输时,人们总是担心大数据文件的大小以及将它们从一个位置交换到另一个位置需要多长时间。由于数据捕获高分辨率视频和图像的日益复杂,文件的大小不断增加。数据工作流在地理上变得越来越分散。在一个位置生成的文件在其他位置处理或使用。…...

Spring Boot 日志
目录 1.概述 2.切换日志实现 3.使用 3.1.日志级别 3.3.日志离线 3.4.详细定制 1.概述 由一些历史原因,JAVA领域存在有很多日志框架,如Log4j、Logback、log4j2。 log4j是Java日志框架的元老,在log4j被Apache Foundation收入门下之后&a…...

好用的研发管理看板工具有哪些?10款主流看板管理软件盘点
10大企业看板工具软件:1.软件开发项目看板 PingCode;2.通用看板软件 Worktile;3.开源看板软件 Wekan;4.免费看板软件 Trello;5.个人和小团队的看板软件 Todoist ;6.开源免费看 Kanboard;7.面向个…...

【软考系统架构设计师】2022下案例分析历年真题
【软考系统架构设计师】2022下案例分析历年真题 【软考系统架构设计师】2022下案例分析历年真题【软考系统架构设计师】2022下案例分析历年真题2022下案例分析历年真题第一题(25分)2022下案例分析历年真题第二题(25分)2022下案例分…...
Java skill - @JsonAlias 和 @JsonProperty
Java skill - JsonAlias 和 JsonPropertyJava skill系列目录:JsonAlias 和 JsonProperty使用 JsonProperty 的麻烦场景:使用 JsonAlias 应对麻烦场景:Java skill系列目录: 【Java skill - 统计耗时用StopWatch】 【Java skill - …...

【实际开发18】- 静态 3
目录 1. 调试与评估 2. 单元测试的管理 1. 单元测试的文档 3. 系统集成的模式与方法 1. 集成测试前的准备 2. 集成测试的模式 3. 大棒集成方法 ( Big-bang Integration) 4. 自顶向下和自底向上集成方法 1. 自顶向下法 ( Top-down Integration ) 2. 自底向上法 ( Bott…...

【swagger2】开发api文档
文章目录一、swagger2 简介背景Open API ???swagger2的作用swagger2常用工具组件:二、Springfox三、springBoot使用swagger2(简单示例)四、Swagger-UI使用五、配置文件1、配置类:给docket上下文配置api描述信息2、配置类&#…...

Github 上如何提交 pull request
什么是复刻(forking)? 我们可以通过复刻操作将喜爱的仓库保存自己的Github账户中,以便独立地对其进行操作。 通过复刻,我们可以得到包含完整版本历史的目标仓库的实例,之后可以对复刻得到的仓库进行任意操作而不会影响…...

Redis面试知识
概述 Redis 是速度非常快的非关系型(NoSQL)内存键值数据库,可以存储键和五种不同类型的值之间的映射。 键的类型只能为字符串,值支持五种数据类型:字符串、列表、集合、散列表、有序集合。 Redis 支持很多特性,例如将内存中的数据持久化到硬盘中,使用复制来扩展读性能…...

Spring面试重点(四)——Spring事务
Spring事务 事务的方式 spring中使用事务有两种方式,一种是编程式事务,一种是声明式事务。编程式事务推荐使用TransactionTemplate,实现TransactionCallback接口,需要编码实现;声明式事务只需要在函数增加注解Transa…...
♡ — MySQL 存储引擎
MySQL 存储引擎架构 MySQL 存储引擎采用的是插件式架构,支持多种存储引擎,我们甚至可以为不同的数据库设置不同的存储引擎以适应不同场景的需要;存储引擎是基于表的,而不是数据库。 MyISAM 和 InnoDB 的区别 MySQL 5.5 之前&am…...

大数据技术架构(组件)34——Spark:Spark SQL--Optimize
2.2.3、Optimize2.2.3.1、SQL3.3.1.1、RB1、Join选择在Hadoop中,MR使用DistributedCache来实现mapJoin。即将小文件存放到DistributedCache中,然后分发到各个Task上,并加载到内存中,类似于Map结构,然后借助于Mapper的迭…...

Zookeeper实现分布式锁
文章目录ZK节点类型watch监听机制Zookeeper实现分布式锁锁原理创建锁的过程释放锁的过程ZK锁的种类代码实现Zookeeper是一个开源的分布式协调服务,是一个典型的分布式数据一致性解决方案。 分布式应用程序可以基于Zookeeper实现诸如数据发布/订阅,负载均…...

深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...

九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...

PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...

ubuntu22.04有线网络无法连接,图标也没了
今天突然无法有线网络无法连接任何设备,并且图标都没了 错误案例 往上一顿搜索,试了很多博客都不行,比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动,重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...
comfyui 工作流中 图生视频 如何增加视频的长度到5秒
comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗? 在ComfyUI中实现图生视频并延长到5秒,需要结合多个扩展和技巧。以下是完整解决方案: 核心工作流配置(24fps下5秒120帧) #mermaid-svg-yP…...

CSS3相关知识点
CSS3相关知识点 CSS3私有前缀私有前缀私有前缀存在的意义常见浏览器的私有前缀 CSS3基本语法CSS3 新增长度单位CSS3 新增颜色设置方式CSS3 新增选择器CSS3 新增盒模型相关属性box-sizing 怪异盒模型resize调整盒子大小box-shadow 盒子阴影opacity 不透明度 CSS3 新增背景属性ba…...