数据结构(2)——线性表与顺序表实现
目录
前言
一、线性表
二、顺序表
2.1概念
2.2类型的选择
2.3实现
1.初始化
2.检查是否需要扩容
3.尾插
4.尾删
5.头插
6.头删
7.某一个位置添加
8.某一个位置删除
9.基于某一位置的尾插删
10.查找
11.修改
12.销毁
总结
前言
今天对顺序表进行学习,可以把它了解成一个连续的表,类似数组。
一、线性表
线性表(linear list)是N个具有相同特性的数据元素的有限数列。线性表是一种在实际中广泛使用的数据结构,常见的线性表有:顺序表、链表、队列、字符串等等。
线性表在逻辑上是线性结构,也就是说连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储的时候,通常以数组和链式的形式存储。数组就是一段连续的地址,链表就是一个指向一个,一个个连在一起像一个链子一样。
线性表是一种数据结构,它由一系列按照顺序排列的元素组成。线性表的特点是元素具有相同的数据类型,元素之间有一个特定的顺序关系。线性表可以简单理解为一维数组,它可以有零个或多个元素。线性表的插入和删除操作比较方便,可以在任意位置插入或删除元素。线性表的查找操作比较耗时,需要遍历整个线性表来查找目标元素。
常见的线性表有顺序表和链表两种。
二、顺序表
2.1概念
顺序表使用的是一段连续的物理地址的存储单元一次存储数据元素的线性结构,一般情况下采用的是数组存储,在数组上完成数据的增删改查,因为基本的就是掌握增删改查就可以。
2.2类型的选择
顺序表可以分为:
1、静态顺序表:使用定长数组存储元素
2、动态顺序表:使用动态开辟实现变长数组存储元素
静态顺序表:
typedef int SLDataType;
typedef struct SeqList
{SLDataType data[20];int size;
}SL;
这里使用的是一个定长数组实现的数据存储,但是有一个弊端,当我们使用的时候难道就放这么多吗?如果我们就往里放一个数据,那那些剩余的就出现了内存的浪费,如果我们多于20,那么又会出现越界,空间不够。也许这时候,你会这么规定,使用define来在开头定义一个变量,后续改动这里就可以了:
#define N 20
typedef int SLDataType;
typedef struct SeqList
{SLDataType data[N];int size;
}SL;
但是你又是怎么确定我一定要用我给的空间个,倘若用的多了,你还要改代码,多麻烦,所以这里就直接使用的是动态开辟空间,先给出一个少一点的空间,如果比原来的空间大了,我可以自动开辟出几个空间,方便下一回使用,这样才是最方便的。
#define InitNum 4
typedef int SLDataType;
typedef struct SeqList
{SLDataType* data;int size;int capacity;
}SL;
我们结构体选用一个方便后续动态开辟的,成员包括数据数组,当前有数据的个数,当前的容量。
2.3实现
这里实现增删改查,分别实现的功能有初始化,头删,头插,尾删,尾插,修改,查元素。我们开始实现:
1.初始化
void SL_Init(SL* pc)
{pc->data = (SLDataType*)malloc(sizeof(SLDataType) * InitNum);if (pc->data == NULL){perror("Data malloc::");return;}pc->size = 0;pc->capacity = InitNum;
}
这里通过动态开辟一个大小为InitNum(4)的数组,当前有效数据的数量变为0,容量大小为4。
2.检查是否需要扩容
当我们在插入数据的时候,需要判断是否容量已经满了,所以这里来封装一个函数用来检查当前是否已经满了,满了就增加容量,没有满就不加。
void SLCheckCapacity(SL* pc)
{assert(pc);if (pc->size == pc->capacity){SLDataType* pf = (SLDataType)realloc(pc->data, sizeof(SLDataType) * pc->capacity*2);if (pf == NULL){perror("SL Calloc::");return;}pc->data = pf;}pc->capacity *= 2;
}
这里进行检查顺序表pc,如果有效数据的个数等于了容量,那就证明了满了,就可以动态开辟内存了。这里每一次开辟二倍。
3.尾插
尾插就是在后面插入数据
void SLPushBack(SL* pc, SLDataType x)
{assert(pc);//需要检查是否需要扩容SLCheckCapacity(pc);//pc->data[pc->size] = x;//pc->size++;pc->data[pc->size++] = x;
}
这里注释的两行代码是和最后一句一样的,用哪一个都可以。
我们可以通过打印来看一看:

我们发现是可以实现的。
4.尾删
尾删这里可以不用真正意义的删去,我们只需要在它显示的时候少去最后的一个就可以:
void SLPopBack(SL* pc, int x)
{assert(pc->size > 0);pc->size--;
}
因为首先要看空间里面还有没有数据,没有数据那还少什么,所以首先断言一下。然后有效数据减一就可以了。

我们运行一下,这里尾插四个数,尾删两次,最后只会输出前两个。
5.头插
头插涉及到一个问题,就是你每插入一个数据,后面的数据就会移动一趟,这样才能有地方存放要头插的数据。
void SLPushHead(SL* pc, SLDataType x)
{assert(pc);int end = pc->size - 1;//最后一个有效数据下标SLCheckCapacity(pc);//检查扩容while (end >= 0){pc->data[end + 1] = pc->data[end];end--;}pc->data[0] = x;pc->size++;
}
经过一个从后往前的遍历就可以实现。

因为是从前面加的,所以第首先加的数会被遍历到后面。
6.头删
头删就是头插的反向思维,就是后一个数据把前面的数据覆盖,有效数据个数减一。
void SLPopHead(SL* pc)
{assert(pc);assert(pc->size > 0);int begin = 0;while (begin <= pc->size - 1){pc->data[begin + 1] = pc->data[begin];begin++;}pc->size--;
}
也是通过一个循环就可以搞定。

7.某一个位置添加
也是在某一个地方添加,那么在这个新加入数据的后面的所有元素都要往后移动一个。
void SLInsert(SL* pc, int pos,SLDataType x)
{assert(pc);assert(pos >= 0 && pos <= pc->size);int end = pc->size - 1;while (end >= pos){SLCheckCapacity(pc);pc->data[end + 1] = pc->data[end];--end;}pc->data[pos] = x;pc->size++;
}
这里是在某一个地方进行添加,记住这里添加完新元素的位置是当前位置的后一个元素。

这里就是头插之后再第二个元素的后面插入1,第三个元素的后面插入2,第四个元素的后面插入3。
8.某一个位置删除
void SLEarse(SL* pc, int pos)
{assert(pc);assert(pc->size > 0);assert(pos >= 0 && pos < pc->size+1);int begin = pos + 1;while (begin <= pc->size){pc->data[begin - 1] = pc->data[begin];++begin;}pc->size--;
}
这里就是和之前添加相反,但是如果像我一样写的话,这里的pos判断范围就发生了变化,注意一下

这里运行一下,win了。
9.基于某一位置的尾插删
那么之前的尾插尾删就可以这么写:
void SLPushBack(SL* pc, SLDataType x)
{assert(pc);//需要检查是否需要扩容SLCheckCapacity(pc);SLInsert(pc, pc->size,x);
}void SLPopBack(SL* pc)
{assert(pc->size > 0);SLEarse(pc, pc->size - 1);
}
这样也可以实现,也是同样的道理。
10.查找
查找一个遍历就解决了
void SLFind(SL* pc, SLDataType x)
{assert(pc);for (int i = 0; i < pc->size; i++){if (pc->data[i] == x){printf("%d",i);return;}}printf("-1");
}
如果找到了就打印下标,没有找到就打印-1.
11.修改
void SLChange(SL* pc, int pos, SLDataType x)
{assert(pc);assert(pos > 0 && pos < pc->size + 1);pc->data[pos-1] = x;
}
这里就是直接通过下标访问一下就可以

12.销毁
销毁也就是释放空间,把申请的都释放掉,还给操作系统。其它的数据都置为0.
void SLDestory(SL* pc)
{assert(pc);free(pc->data);pc->data = NULL;pc->capacity = pc->size = 0;
}
这样基本的就大差不差都完事了。
总结
今天主要对线性表进行了了解,以及顺序表的实现和基本操作进行了编写。
相关文章:
数据结构(2)——线性表与顺序表实现
目录 前言 一、线性表 二、顺序表 2.1概念 2.2类型的选择 2.3实现 1.初始化 2.检查是否需要扩容 3.尾插 4.尾删 5.头插 6.头删 7.某一个位置添加 8.某一个位置删除 9.基于某一位置的尾插删 10.查找 11.修改 12.销毁 总结 前言 今天对顺序表进行学习…...
全面解析机器学习优化算法中的进化策略
全面解析机器学习优化算法中的进化策略 全面解析机器学习优化算法中的进化策略引言什么是进化策略?基本概念核心组件算法流程数学基础高斯扰动期望值更新与其他优化方法的比较梯度下降法(Gradient Descent, GD)遗传算法(Genetic Algorithm, GA)Python案例基本实现改进版:…...
【LeetCode】5. 贪心算法:买卖股票时机
太久没更了,抽空学习下。 看一道简单题。 class Solution:def maxProfit(self, prices: List[int]) -> int:cost -1profit 0for i in prices:if cost -1:cost icontinueprofit_ i - costif profit_ > profit:profit profit_if cost > i:cost iret…...
软件测试丨PyTorch 图像目标检测
随着人工智能和机器学习的飞速发展,图像目标检测技术在各个领域扮演着越来越重要的角色。无论是在安防监控、自动驾驶车辆,还是在医疗影像分析和智能家居中,图像目标检测都发挥着不可或缺的作用。今天,我们将深入探讨其中一种热门…...
SpringSecurity密码编码器:使用BCrypt算法加密、自定义密码编码器
1、Spring Security 密码编码器 Spring Security 作为一个功能完备的安全性框架,一方面提供用于完成加密操作的 PasswordEncoder 组件,另一方面提供一个可以在应用程序中独立使用的密码模块。 1.1 PasswordEncoder 抽象接口 在 Spring Security 中,PasswordEncoder 接口代…...
FastReport.NET控件篇之交叉表控件
认识交叉表 上面是交叉表的原型,关键的三个单元格。 单元格①:用于扩展行数据,譬如打印学生成绩表时,每个学生一行,那么这个地方就是以学生姓名列进行打印。 单元格②:用于扩展列数据,譬如打印…...
互联网医院开发|互联网医院成品|互联网医院系统定制
互联网医院开发设计风格需综合考量多方面因素,以确保其专业性、易用性与高效性。在界面设计上,应遵循简洁直观的原则。避免过于繁杂的布局,确保关键功能模块清晰呈现,方便用户快速定位与操作。色彩搭配要注重视觉舒适度与专业性&a…...
17.3.4 颜色矩阵
版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。 17.3.4.1 矩阵基本概念 矩阵(Matrix)是一个按照长方阵列排列的复数或实数集合,类似于数组。 由…...
【C++】多态详细讲解
本篇来聊聊C面向对象的第三大特性-多态。 1.多态的概念 多态通俗来说就是多种形态。多态分为编译时多态(静态多态)和运⾏时多态(动态多态)。 编译时多态:主要就是我们前⾯讲的函数重载和函数模板,他们传不同类型的参数就可以调⽤不同的函数,通…...
4. k8s二进制集群之ETCD集群证书生成
安装cfssl工具配置CA证书请求文件创建CA证书创建CA证书策略配置etcd证书请求文件生成etcd证书 继续上一篇文章《负载均衡器高可用部署》下面介绍一下etcd证书生成配置。其中涉及到的ip地址和证书基本信息请替换成你自己的信息。 安装cfssl工具 下载cfssl安装包 https://github…...
Drools规则引擎初体验
前言 假设有这样一个场景,订单管理系统需要根据用户的消费情况,来为每个用户发放不同程度的优惠券,这个发放规则复杂且多变,我们该怎么办?在代码中写死显然是不可取的,规则一变就要修改代码,频…...
Day36【AI思考】-表达式知识体系总览
文章目录 **表达式知识体系总览**回答1:**表达式知识体系****一、三种表达式形式对比****二、表达式转换核心方法****1. 中缀转后缀(重点)****2. 中缀转前缀** **三、表达式计算方法****1. 后缀表达式计算(栈实现)****…...
Tailwind CSS v4.0 升级与 Astro 5.2 项目迁移记录
本文博客链接 https://ysx.cosine.ren/tailwind-update-v4-migrate 自用小记。 Tailwind CSS v4.0 - Tailwind CSS 新的高性能引擎 - 完整构建的速度速度快 5 倍,增量构建的速度快于 100 倍以上 —— 以微秒为单位进行测量。为现代 Web 设计 - 建立在前沿的 CSS 特…...
K8S ReplicaSet 控制器
一、理论介绍 今天我们来实验 ReplicaSet 控制器(也叫工作负载)。官网描述如下: 1、是什么? ReplicaSet 副本集, 维护一组稳定的副本 Pod 集合。 2、为什么需要? 解决 pod 被删除了,不能自我恢…...
基于springboot校园点歌系统
基于Spring Boot的校园点歌系统是一种专为校园场景设计的音乐点播平台,它能够丰富学生的校园生活,提升学生的娱乐体验。以下是对该系统的详细介绍: 一、系统背景与意义 在校园环境中,学生们对于音乐有着浓厚的兴趣,传…...
【R语言】数据操作
一、查看和编辑数据 1、查看数据 直接打印到控制台 x <- data.frame(a1:20, b21:30) x View()函数 此函数可以将数据以电子表格的形式进行展示。 用reshape2包中的tips进行举例: library("reshape2") View(tips) head()函数 查看前几行数据&…...
【C++】2.高并发内存池 -- 如何设计一个定长内存池
博客主题:如何设计一个定长内存池 个人主页:https://blog.csdn.net/sobercq CSDN专栏:https://blog.csdn.net/sobercq/category_12884309.html Gitee链接:https://gitee.com/yunshan-ruo/high-concurrency-memory-pool 文章目录 前…...
Redis --- 使用Feed流实现社交平台的新闻流
要实现一个 Feed 流(类似于社交媒体中的新闻流),通常涉及以下几个要素: 内容发布:用户发布内容(例如文章、状态更新、图片等)。内容订阅:用户可以订阅其他用户的内容,获…...
React中key值的正确使用指南:为什么需要它以及如何选择
React中key值的正确使用指南:为什么需要它以及如何选择 一、key值的基本概念二、如何选择合适的key值1. 数据来源决定key策略2. key值的三大核心要求 三、React为何需要key值?1. 虚拟DOM优化机制2. 状态维护机制 四、常见误区及解决方案1. 索引作为key的…...
在Debian 12上安装VNC服务器
不知道什么标题 可以看到这个文章是通过豆包从国外网站copy的,先这样写着好了,具体的我有时间再补充,基本内容都在这里了。 在Debian 12上安装VNC服务器 简介 VNC(Virtual Network Computing,虚拟网络计算…...
游戏引擎学习第88天
仓库:https://gitee.com/mrxiao_com/2d_game_2 调查碰撞检测器中的可能错误 在今天的目标是解决一个可能存在的碰撞检测器中的错误。之前有人提到在检测器中可能有一个拼写错误,具体来说是在测试某个变量时,由于引入了一个新的变量而没有正确地使用它&…...
c++中priority_queue的应用及模拟实现
1.介绍 priority_queue 是一种数据结构,它允许你以特定的顺序存储和访问元素。在 C 标准模板库(STL)中,priority_queue 是一个基于容器适配器的类模板,它默认使用 std::vector 作为底层容器,并且默认使用最…...
深度学习篇---计算机视觉任务模型的剪裁、量化、蒸馏
文章目录 前言第一部分:计算机视觉任务图像分类特点 图像识别特点 目标检测特点 图像分割子任务特点 第二部分:模型剪裁、量化、蒸馏模型剪裁1.权重剪裁2.结构剪裁3.迭代剪裁 模型量化1.对称量化2.非对称量化3.动态量化4.静态量化 知识蒸馏1.训练教师网络…...
java-关键字(final,static)
关键字 final 和 static 是两个常用的关键字,它们分别用于不同的场景,具有不同的作用。 final final 关键字用于表示某个实体是不可变的。它可以应用于变量、方法和类。 final 变量 当 final 用于变量时,表示该变量一旦被初始化后&#…...
游戏引擎 Unity - Unity 设置为简体中文、Unity 创建项目
Unity Unity 首次发布于 2005 年,属于 Unity Technologies Unity 使用的开发技术有:C# Unity 的适用平台:PC、主机、移动设备、VR / AR、Web 等 Unity 的适用领域:开发中等画质中小型项目 Unity 适合初学者或需要快速上手的开…...
JDK17主要特性
JDK 17,也被称为Java 17或Java Platform, Standard Edition 17,是Java编程语言的第十七个主要版本,由Oracle公司在2021年9月发布。Java 17是一个长期支持(LTS,Long-Term Support)版本,这意味着它…...
将OneDrive上的文件定期备份到移动硬盘
背景: 我在oneDrive上存了很多文件,分布在多个文件夹中,也有套了好几层文件夹的情况。我希望每隔一段时间,将oneDrive上的所有文件向移动硬盘上拷贝一份,但是我只想将距离上一次向移动硬盘拷贝的文件相比,发…...
【Elasticsearch】geohex grid聚合
在 Elasticsearch 中,地理边界过滤是一种用于筛选地理数据的技术,它可以根据指定的地理边界形状(如矩形、多边形等)来过滤符合条件的文档。这种方法在地理空间数据分析中非常有用,尤其是在需要将数据限制在特定地理区域…...
crewai框架第三方API使用官方RAG工具(pdf,csv,json)
最近在研究调用官方的工具,但官方文档的说明是在是太少了,后来在一个视频里看到了如何配置,记录一下 以PDF RAG Search工具举例,官方文档对于自定义模型的说明如下: 默认情况下,该工具使用 OpenAI 进行嵌…...
算法 哈夫曼树和哈夫曼编码
目录 前言 一,二进制转码 二,哈夫曼编码和哈夫曼树 三,蓝桥杯 16 哈夫曼树 总结 前言 这个文章需要有一定的树的基础,没学过树的伙伴可以去看我博客树的文章 当我们要编码一个字符串转成二进制的时候,我们要怎么…...
