数据结构:顺序表详解

1.顺序表的概念与定义

2.顺序表的初始化与销毁

3.顺序表的头/尾部的插入与删除

4.顺序表指定位置的插入和删除

4.对顺序表中的数据的查找

5.总结

我以过客之名,祝你前程似锦


一.顺序表的概念与定义

1.概念:

顺序表是在计算机内存中以数组的形式保存的线性表,线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素、使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系,采用顺序存储结构的线性表通常称为顺序表。顺序表是将表中的结点依次存放在计算机内存中一组地址连续的存储单元中

2.定义:

 (1)数据类型定义:
typedef struct   //定义数据类型
{int size;int capability;
}Seqlist;
 (2)顺序表的定义:
#define  _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>typedef struct   //定义数据类型
{int size;int capability;
}Seqlist;typedef int SLDataType;
typedef struct SeqList
{SLDataType* a;int size;     // 有效数据个数int capacity; // 空间容量}SL;              //命名了一个数据类型为struct Seqlist的叫SL的顺序表

二.顺序表的初始化与销毁

1.初始化:

以下是将初始化分装为函数并且在text.c里调用以便调试(接下来会有很多处这样的分装)

这里有一个非常值得注意的地方:就是对于顺序表的传址调用是用的一级指针,而在后续的链表却使用的是二级指针,这其中主要的原因是:

两者在内存管理方式上的差异。‌

顺序表和链表的基本概念和操作方式
‌顺序表‌:顺序表是将数据依次存储在连续的整块物理空间中,通过计算地址可以直接访问任何数据元素。顺序表的尾插操作是通过调整数组的容量和索引来实现的,不需要改变原有指针的指向,因此传递一级指针即可
链表‌:链表是通过节点之间的链接来存储数据,每个节点包含数据部分和指向下一个节点的指针。链表的尾插操作需要创建一个新节点,并将其链接到链表的末尾,同时更新尾指针。由于需要修改指针的指向,因此必须传递二级指针(即指针的地址)

如果这里不太理解的话不用担心,下面还会进行详细介绍的

2.销毁(置0):

不同于链表的销毁,顺序表的销毁只不过是将原有的数据清零(覆盖),而顺序表需要通过使用free函数释放掉每个结点的内存(在顺序表的介绍里我会不时地提到链表,一是因为这俩确实很像,同时也方便你对这俩兄弟的理解,所有如果对于链表还不了解的兄弟可以适当忽略我在这里写的话,后面自然而然就会懂了,加油)


三.顺序表的头/尾部的插入与删除

1.尾插(从顺序表尾部插入):

void SLPushBack(SL* ps, SLDataType x)
{//方法一,判断用户传入的是否为空指针//if (ps == NULL)//{//	return;//}//方法二assert(ps);//ps->arr[ps->size++] = x;//插入数据前看空间够不够if(ps->capacity==ps->size){//申请空间int newCapacity = ps->capacity == 0 ? 4 : 2*sizeof(SLDataType);//防止初始化的capacity为0(也可以直接在初始化就申请)//ps->arr = realloc(ps->arr, newCapacity * sizeof(SLDataType));//万一申请空间不成功(malloc申请空间不一定成功)SL*tmp =(SL*) realloc(ps->arr, newCapacity * sizeof(SLDataType));if (tmp == NULL){perror("realloc failed!");exit(1);//直接退出程序}//空间申请成功ps->arr = tmp;ps->capacity = newCapacity;}ps->arr[ps->size++] = x;
}

别紧张,虽然代码量看着比较多,但也就那几个部分,我在这里详细讲讲这个尾插的解法,其他的代码就会很简单了

第二部分如果后续觉得在每一个插入的地方都重复使用的话会显得有些繁琐,所以这里我们也可以单独把他拎出来封装成另外一个函数(即我们的检验扩容函数

同时我再说一下那个三目操作符为什么是2 * sizeof(SLDataType),主要是通过数学逻辑证明每次扩大二倍的效率最高

//检验,扩容
void SLCheckCapacity(SL* ps)
{//插入数据前看空间够不够if (ps->capacity == ps->size){//申请空间int newCapacity = ps->capacity == 0 ? 4 : 2 * sizeof(SLDataType);//防止初始化的capacity为0(也可以直接在初始化就申请)//ps->arr = realloc(ps->arr, newCapacity * sizeof(SLDataType));//万一申请空间不成功(malloc申请空间不一定成功)SL* tmp = (SL*)realloc(ps->arr, newCapacity * sizeof(SLDataType));if (tmp == NULL){perror("realloc failed!");exit(1);//直接退出程序}//空间申请成功ps->arr = tmp;ps->capacity = newCapacity;}
}

2.头插(理解了尾插后头插就会显得容易多了):

//头插
void SLPushFront(SL* ps, SLDataType x)
{assert(ps);SLCheckCapacity(ps);//先让顺序表中已有的数据往后挪动一位for (int i = ps->size; i>0; i--){ps->arr[i] = ps->arr[i - 1];//为了确保最后一次挪动为arr[0]=arr[1],故i的范围要注意}ps->arr[0] = x;ps->size++;//插入数据的同时也要使size跟着变动
}

3.尾删:

//尾删
void SLPopBack(SL* ps)
{assert(ps && ps->size);//尾删时一个要注意的时顺序表本身不为空,另外一个里面的有效数据个数(size)不为0--ps->size;
}

注意:这里assert的两个限制条件都是为了确保顺序表里有元素的存在

4.头删:

//头删
void SLPopFront(SL* ps)
{assert(ps && ps->size);//顺序表不为空for (int i = 0; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];//所有数据向前挪动一位,比如arr[1]=arr[0]}--ps->size;//有效数据再减一,兄弟,这里是真的容易忘(捂脸)
}

注意:最后一个有效数据减一


四.顺序表指定位置的插入和删除

1.指定位置的插入:

//指定位置插入数据
void SeqListInsert(SL* ps, int pos, SLDataType x)//pos是下标
{assert(ps);assert(pos >= 0 && pos <= ps->size);SLCheckcapacity(ps);//正常检查空间是否充足int i = 0;for (i = pos; i < ps->size; i++){ps->arr[i + 1] = ps->arr[i];}//使pos后面的数据一起往后挪动一位ps->arr[pos] = x;++ps->size;
}

2.指定位置的删除:

void SeqListErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos <= ps->size);int i = 0;for (i = pos;i < ps->size-1;i++){ps->arr[i] = ps->arr[i+1];}--ps->size;
}

五.对顺序表中的数据的查找

//查找
int SeqListFind(SL* ps, SLDateType x)
{int i = 0;for (i = 0;i < ps->size;i++){if (ps->arr[i] == x){return i;}}//遍历整个顺序表return 0;//没找到
}

其实只要把开头的尾插搞懂,下面的一系列代码也就迎刃而解了,跟做减法一样


六.总结

顺序表要预先分配空间,会导致空间闲置或溢出,采用随机存取,

时间复杂度为O(1),但删除和插入要一项一项的移动,时间复杂度为O(n)

适用情况

1.表长变化不大,且能事先确定变化的范围

2.很少进行插入或删除操作,经常按元素序号访问数据元素

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

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

相关文章

【算法】棋盘覆盖问题源代码及精简版

目录 一、题目 二、样例 三、示例代码 四、精简代码 五、总结 对于棋盘覆盖问题的解答和优化。 一、题目 输入格式&#xff1a; 第一行&#xff0c;一个整数n&#xff08;棋盘n*n&#xff0c;n确保是2的幂次&#xff0c;n<64&#xff09; 第二行&#xff0c;两个整数…

摩尔线程 国产显卡 MUSA 并行编程 学习笔记-2024/12/04

Learning Roadmap&#xff1a; Section 1: Intro to Parallel Programming & MUSA Deep Learning Ecosystem&#xff08;摩尔线程 国产显卡 MUSA 并行编程 学习笔记-2024/11/30-CSDN博客&#xff09;UbuntuDriverToolkitcondapytorchtorch_musa环境安装(2024/11/24-Ubunt…

App如何跨线上线下、跨渠道、跨终端归因分析

随着渠道分布多元化、生态割裂加剧、用户时间碎片化等趋势&#xff0c;多渠道投放已经成为不可阻挡的广告投放趋势。 但是App营销推广渠道那么多&#xff0c;既要确保广告效果好&#xff0c;又要避免广告资源浪费&#xff0c;有限的媒体预算应该分配给哪几个渠道&#xff1f;哪…

leetcode 3001. 捕获黑皇后需要的最少移动次数 中等

现有一个下标从 1 开始的 8 x 8 棋盘&#xff0c;上面有 3 枚棋子。 给你 6 个整数 a 、b 、c 、d 、e 和 f &#xff0c;其中&#xff1a; (a, b) 表示白色车的位置。(c, d) 表示白色象的位置。(e, f) 表示黑皇后的位置。 假定你只能移动白色棋子&#xff0c;返回捕获黑皇后…

Day6:生信新手笔记 — R包安装与R包使用

R包是多个函数的集合。学生信使用R语言的原因是丰富的图表和Biocductor上面的各种生信分析R包。 一、安装和加载R包 1.设置镜像 镜像网站相当于主网站的副本&#xff0c;访问主网站存在障碍时&#xff0c;访问镜像网站也可。选择国内的镜像可加快访问速度。运行这两行代码&a…

Spring源码解读

文章目录 Spring简单容器(以BeanFactory为主)Spring高级容器(以ApplicationCOntext为主)ListableBeanFactoryobtainFreshBeanFactory()获取BeanFactorySpring源码学习:一篇搞懂@Autowire和@Resource注解的区别Spring简单容器(以BeanFactory为主) Spring高级容器(以Appl…

达梦数据库客户端安装方法

达梦数据库客户端安装方法 达梦客户端下载地址 产品下载 | 达梦数据库 下载完成后以后是这样子的 dm8_20241011_x86_win_64.zip 然后解压 解压后的结果 双击iso的文件 然后选中 然后下一步 自定义安装路径然后下一步 安装 然后直接在开始这里搜DM管理工具 然后配置连接即…

【北京迅为】iTOP-4412全能版使用手册-第五十五章 字符类GPIOS

iTOP-4412全能版采用四核Cortex-A9&#xff0c;主频为1.4GHz-1.6GHz&#xff0c;配备S5M8767 电源管理&#xff0c;集成USB HUB,选用高品质板对板连接器稳定可靠&#xff0c;大厂生产&#xff0c;做工精良。接口一应俱全&#xff0c;开发更简单,搭载全网通4G、支持WIFI、蓝牙、…

LabVIEW算法执行时间评估与Windows硬件支持

在设计和实现复杂系统时&#xff0c;准确估算算法的执行时间是关键步骤&#xff0c;尤其在实时性要求较高的应用中。这一评估有助于确定是否需要依赖硬件加速来满足性能需求。首先需要对算法进行时间复杂度分析并进行实验测试&#xff0c;了解其在Windows系统中的运行表现。根据…

D614 PHP+MYSQL +失物招领系统网站的设计与现 源代码 配置 文档

失物招领系统 1.摘要2. 系统开发的背景和意义3.功能结构图4.界面展示5.源码获取 1.摘要 随着互联网的迅速发展&#xff0c;人们的生产生活方式逐渐发生改变&#xff0c;传统的失物招领也可以通过网络处理。本网站是基PHP技术的一款综合性较强的西南民族大学PHP失物招领系统。 …

【Java】Switch语句、循环语句(for、while、do...while)

Switch语句&#xff1a;针对某个表达式的值进行判断&#xff0c;从而决定执行哪一段代码 语法格式&#xff1a; switch(表达式){ case 目标值1: 执行语句1 break; case 目标值2: …

中建海龙:科技创新引领建筑业革新,铸就行业影响力

在建筑业这个古老而又充满活力的行业中&#xff0c;中建海龙科技有限公司&#xff08;以下简称“中建海龙”&#xff09;凭借其卓越的科技实力和一系列荣誉奖项&#xff0c;正逐步确立其在建筑工业化领域的领导地位&#xff0c;并对整个行业产生了深远影响。 中建海龙自成立以来…

【认证法规】安全隔离变压器

文章目录 定义反激电源变压器 定义 安全隔离变压器&#xff08;safety isolating transformer&#xff09;&#xff0c;通过至少相当于双重绝缘或加强绝缘的绝缘使输入绕组与输出绕组在电气上分开的变压器。这种变压器是为以安全特低电压向配电电路、电器或其它设备供电而设计…

引领素养教育行业,猿辅导素养课斩获“2024影响力教育品牌”奖项

近日&#xff0c;由教育界网、校长邦联合主办&#xff0c;鲸媒体、职教共创会协办的“第9届榜样教育年度盛典”评奖结果揭晓。据了解&#xff0c;此次评选共有近500家企业提交参评资料进行奖项角逐&#xff0c;历经教育界权威专家、资深教育从业者以及专业评审团队的多轮严格筛…

内网穿透 natapp安装与使用

前言 NATAPP是一款基于ngrok的内网穿透工具。以下是对NATAPP的详细概述&#xff1a; 基本概念 定义&#xff1a;内网穿透&#xff08;NAT穿透&#xff09;是一种技术&#xff0c;它允许具有特定源IP地址和端口号的数据包能够绕过NAT设备&#xff0c;从而被正确地路由到内网主机…

TiDB如何保证数据一致性

1. 分布式事务协议 TiDB 采用了类似 Google Percolator 的分布式事务协议来处理分布式事务。这个协议基于两阶段提交&#xff08;2PC&#xff09;的思想&#xff0c;但进行了优化和改进&#xff0c;以适应分布式环境的特殊需求。在 TiDB 中&#xff0c;当一个事务需要跨多个节…

高中数学:导数-在研究函数中的应用

文章目录 一、函数单调性解题步骤图像特征与导数值的关系 二、函数的极值与最大最小值1、函数的极值极值点的求法2、函数的最大最小值最大最小值求法函数大致图像的画法 一、函数单调性 例题 解题步骤 例题 图像特征与导数值的关系 二、函数的极值与最大最小值 1、函数的极…

OceanBase数据库使用 INSERT 语句违反唯一约束冲突解决办法及两者差异分析

当在OceanBase数据库上创建带有唯一性约束的表&#xff0c;在向表中插入唯一性约束的冲突的数据时会提示因违反唯一性约束报错&#xff0c;OceanBase在其官网上提供了两种解决策略&#xff0c;但其官网并未详细说明两种策略的差异&#xff0c;于是早上对两种策略进行一些测试&a…

【人工智能的深度分析与最新发展趋势】

人工智能的深度分析与最新发展趋势 引言 人工智能&#xff08;AI&#xff09;是现代科技的重要组成部分&#xff0c;它涉及模拟人类智能的算法和技术。随着计算能力的提升和数据量的激增&#xff0c;AI的应用正在迅速渗透到各个行业。本文将深入分析人工智能的概念、技术、应…

Spring Boot + MySQL 多线程查询与联表查询性能对比分析

Spring Boot MySQL: 多线程查询与联表查询性能对比分析 背景 在现代 Web 应用开发中&#xff0c;数据库性能是影响系统响应时间和用户体验的关键因素之一。随着业务需求的不断增长&#xff0c;单表查询和联表查询的效率问题日益凸显。特别是在 Spring Boot 项目中&#xff0…