当前位置: 首页 > news >正文

顺序表(超详解哦)

全文目录

  • 引言
  • 顺序表定义
    • 静态顺序表
    • 动态顺序表
  • 动态顺序表的接口实现
    • 顺序表的初始化与销毁
    • 顺序表尾插/尾删
    • 顺序表头插/头删
    • 顺序表在pos位置插入/删除
    • 顺序表的打印
    • 顺序表中的查找
  • 总结

引言

在生产中,为了方便管理数据,我们经常会需要将一些数据连续的存储起来。例如手机的通讯录中需要存储联系人的信息;图书管理系统中需要存储图书的信息等。

想到存储一系列相同类型的数据,我们就不免想到数组。数组可以实现将一些相同类型的数据存储到一块连续的空间中。其实,我们在这篇文章中要介绍的顺序表中的数据就是以数组的形式存储的。

顺序表定义

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。

为了方便管理数据,我们通常会将存储数据的数组与目前数据的状态(顺序表中已经存储元素的个数等)放在一个结构体变量中。

静态顺序表

静态顺序表就是使用定长的数组存储数据的顺序表。

我们需要将存储数据的数组与当前已存储的数据的个数放在一个结构体变量中,以方便对数据进行管理:

typedef int SLDateType;typedef struct SeqList
{SLDateType arr[10];size_t size;
}SeqList;

但是,这样存储数据是有很明显的缺陷的:就是空间的大小一旦确定下来就不能改变了,当数据存储满之后也不能实现扩容。

所以,我们可以使用动态顺序表来实现:

动态顺序表

动态顺序表就是使用动态开辟的数组存储数据的顺序表:

我们需要将存储数据的动态空间的地址、当前已经存储的数据的个数与顺序表的容量大小放在一个结构体变量中,方便对数据进行管理:

typedef int SLDateType;typedef struct SeqList
{SLDateType* arr;size_t size;size_t capacity;
}SeqList;

在这里插入图片描述

SLDateType* arr指向的空间是动态开辟的,当需要扩容时,只需要使用realloc函数进行扩容即可。

动态顺序表的接口实现

在有了顺序表的相关概念后,我们就可以尝试实现一下顺序表
静态顺序表的实现其实是较为简单的,这里就只介绍动态顺序表的实现:

首先,我们需要将上述的SeqList类型的结构体定义出来。但此时它的成员为一个SLDateType*型的指针、任意值的size变量与capacity变量。并没有任何意义,所以,我们需要对这个结构体中的成员进行初始化:

顺序表的初始化与销毁

初始化函数:void SeqListInit(SeqList* ps);

对于初始化函数,只有一个参数就是我们创建的结构体的结构体指针。在这个函数中,我们需要实现动态开辟一块空间用来存放数据,并且将size与capacity的值初始化为0:

void SeqListInit(SeqList* ps)
{assert(ps);ps->arr = (SLDateType*)calloc(INIT, sizeof(SLDateType));if (ps->arr == NULL){perror(calloc);return;}ps->capacity = INIT;ps->size = 0;
}

我们的空间是动态开辟的,在使用结束后自然需要free释放

内存释放函数:void SeqListDestroy(SeqList* ps)

void SeqListDestroy(SeqList* ps)
{assert(ps);free(ps->arr);ps->arr = NULL;ps->capacity = 0;ps->size = 0;
}

有了存储数据的空间,我们就需要实现对这些数据的操作:无非增、删、查、改。
我们将逐一实现这些操作:

顺序表尾插/尾删

顺序表的尾插就是在顺序表的末尾插入一个值。
我们直接在顺序表中下标为size(结构体中的成员)的位置插入一个数据即可。

但是,这样的想法是有漏洞的,当size等于capacity时,即顺序表已经存满的时候。我们如果还将数据存在下标为size的位置,就会出现数组越界的问题。所以插入数据前,我们需要判断是否需要扩容,如果需要,则使用realloc扩容后再插入数据:
(别忘了插入后size++)

void SeqListPushBack(SeqList* ps, SLDateType x)
{assert(ps);if (ps->capacity == ps->size){SLDateType* ptr = (SLDateType*)realloc(ps->arr, 2 * ps->capacity * sizeof(SLDateType));if (ptr == NULL){perror("realloc");return;}ps->arr = ptr;ps->capacity *= 2;}*(ps->arr + ps->size++) = x; 
}

顺序表的尾删就是删除顺序表中的最后一个数据:

当然,当顺序表中的数据数(size)为0时,就不执行此函数。这里我们可以直接使用assert来判断:
(别忘了删除后size–)

void SeqListPopBack(SeqList* ps)
{assert(ps);assert(ps->size > 0);*(ps->arr + --(ps->size)) = 0;
}

顺序表头插/头删

顺序表的头插就是在顺序表的前面插入一个数据。

此时,我们显然是不能直接用数据覆盖第一个数据的。而是需要将顺序表中的数据整体向后移动一个元素的位置,然后再将第一个元素的位置覆盖。
当然,头插也需要判断顺序表是否已满:
(别忘了插入后size++)

void SeqListPushFront(SeqList* ps, SLDateType x)
{assert(ps);if (ps->capacity == ps->size){SLDateType* ptr = (SLDateType*)realloc(ps->arr, 2 * ps->capacity * sizeof(SLDateType));if (ptr == NULL){perror("realloc");return;}ps->arr = ptr;ps->capacity *= 2;}for(size_t i = ps->size; i > 0; i--){*(ps->arr + i) = *(ps->arr + i - 1);}*ps->arr = x;ps->size++;
}

顺序表的头删就是将顺序表中最前面的元素删除。
首先判断size是否为0。然后我们可以直接用后面的元素覆盖前面一个的元素,这样可以直接实现删除第一个元素:
(别忘了删除后size–)

void SeqListPopFront(SeqList* ps)
{assert(ps);assert(ps->size > 0);for (size_t i = 1; i < ps->size; i++){*(ps->arr + i - 1) = *(ps->arr + i);}ps->size--;
}

顺序表在pos位置插入/删除

实现了头插头删、尾插尾删后,我们再进一步思考,能不能实现在顺序表的任意位置插入或删除任意位置的元素:

在pos位置插入数据时:
同样需要判断是否已满。我们需要将从pos开始的元素向后移动,然后再将元素插入到pos位置即可:
(别忘了插入后size++)

void SeqListInsert(SeqList* ps, int pos, SLDateType x)
{assert(ps);if (ps->capacity == ps->size){SLDateType* ptr = (SLDateType*)realloc(ps->arr, 2 * ps->capacity * sizeof(SLDateType));if (ptr == NULL){perror("realloc");return;}ps->arr = ptr;ps->capacity *= 2;}for (int i = ps->size; i > pos; i--){*(ps->arr + i) = *(ps->arr + i - 1);}ps->size++;*(ps->arr + pos) = x;
}

删除pos位置的元素时,首先判断size是否为0。然后只需要将从pos后的元素统一向前覆盖即可实现pos位置数据的删除:
(别忘了删除后size–)

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

顺序表的打印

打印顺序表中元素时,直接便利顺序表打印即可:

void SeqListPrint(SeqList* ps)
{assert(ps);for (size_t i = 0; i < ps->size; i++){printf("%d ", *(ps->arr + i));}
}

顺序表中的查找

查找顺序表中数据时,只需要将顺序表中度元素遍历,逐个与输入元素比较即可。查找到后,返回下标,否则返回0:

int SeqListFind(SeqList* ps, SLDateType x)
{assert(ps);for (size_t i = 0; i < ps->size; i++){if (*(ps->arr + i) == x){return i + 1;}}return -1;
}

总结

到此,关于顺序表的所有内容就介绍完了。不难发现,这些数据存储的形式可以抽象化为线性,顺序表其实就是线性表的一种。

线性表是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使
用的数据结构,常见的线性表有顺序表、链表、栈、队列、字符串等。

线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,
线性表在物理上存储时,通常以数组和链式结构的形式存储。在下一篇文章我们将要介绍的链表也是线性表的一种。

如果大家认为我对某一部分没有介绍清楚或者某一部分出了问题,欢迎大家在评论区提出

如果本文对你有帮助,希望一键三连哦

希望与大家共同进步哦

相关文章:

顺序表(超详解哦)

全文目录引言顺序表定义静态顺序表动态顺序表动态顺序表的接口实现顺序表的初始化与销毁顺序表尾插/尾删顺序表头插/头删顺序表在pos位置插入/删除顺序表的打印顺序表中的查找总结引言 在生产中&#xff0c;为了方便管理数据&#xff0c;我们经常会需要将一些数据连续的存储起…...

Compose-Animation高级别动画

目录前言AnimatedVisibilityisScrollingUpFABscaffoldanimateContentSizeCrossfade顶部气泡下弹前言 AnimatedVisibility 驱动可视性相关动画&#xff0c;即布局显隐 animateContentSize 内容变换动画相关 Crossfade 布局&#xff08;或者页面&#xff09;切换过渡动画 Animat…...

c++11 标准模板(STL)(std::unordered_set)(八)

定义于头文件 <unordered_set> template< class Key, class Hash std::hash<Key>, class KeyEqual std::equal_to<Key>, class Allocator std::allocator<Key> > class unordered_set;(1)(C11 起)namespace pmr { templ…...

Python每日一练(20230225)

目录 1. 整数反转 2. 求最大公约数和最小公倍数 最大公约数 最小公倍数 3. 单词搜索 II 附录&#xff1a; DFS 深度优先搜索算法 BFS 广度优先搜索算法 BFS 和 DFS 的区别 1. 整数反转 给你一个 32 位的有符号整数 x &#xff0c;返回将 x 中的数字部分反转后的结果。…...

基于博客系统的测试用例

登陆界面博客预览页博客详情页博客编辑页...

C语言运算符算术运算符关系运算符

C 运算符 运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C 语言内置了丰富的运算符&#xff0c;并提供了以下类型的运算符&#xff1a; 算术运算符 关系运算符 逻辑运算符 位运算符 赋值运算符 杂项运算符 本章将逐一介绍算术运算符、关系运算符、逻辑运算符、位运…...

C语言 深度剖析数据在内存中的存储

目录数据类型详细介绍整形在内存中的存储&#xff1a;原码&#xff0c;反码&#xff0c;补码大小端字节序介绍及判断浮点型在内存中的存储解析数据类型详细介绍整形&#xff1a;1.为什么char类型也会归类到整形家族当中去呢&#xff1f;字符存储和表示的时候本质上使用的是ASCI…...

MyBatis快速开发

查询user表中的所有数据 步骤&#xff1a; 创建user表 打开Navicat&#xff0c;新建查询&#xff0c;将下面SQL代码复制粘贴并执行&#xff1a; create database mybatis; use mybatis;drop table if exists tb_user;create table tb_user(id int primary key auto_incremen…...

大数据常见应用场景及架构改进

大数据常见应用场景及架构改进大数据典型的离线处理场景1.大数据数据仓库及它的架构改进2.海量数据规模下的搜索与检索3.新兴的图计算领域4.海量数据挖掘潜在价值大数据实时处理场景大数据典型的离线处理场景 1.大数据数据仓库及它的架构改进 对于离线场景&#xff0c;最典型…...

【华为OD机试模拟题】用 C++ 实现 - 挑选字符串(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 货币单位换算(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 选座位(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 停车场最大距离(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 重组字符串(2023.Q1) 【华为OD机试模…...

程序员是世界上最理性、最睿智的群体,耶稣也反驳不了我,我说的!

有人说&#xff0c;程序员是吃青春饭的&#xff0c;35 岁就提前退休了。 猛一看&#xff0c;这句话是对的&#xff1b;仔细一看&#xff0c;这句话是不对的。 说它对&#xff0c;是因为现实中确实有很多程序员 35 岁就被毕业了&#xff1b;说它不对&#xff0c;是因为 35 岁以…...

人工智能到底是什么?

人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;是一种利用计算机科学和统计学理论和技术来实现人类智能的一门交叉学科&#xff0c;旨在使计算机系统能够模拟、扩展和增强人类的智能能力&#xff0c;使计算机能够像人类一样思考、学习、决策和执行任务…...

在动态规划的海洋中遨游(三)

前言&#xff1a;\textcolor{Green}{前言&#xff1a;}前言&#xff1a; &#x1f49e; 好久没写题&#xff0c;有点生疏了。这也是给大家提一个醒&#xff0c;一定要一直坚持下去&#xff0c;哪怕每天只做一点点。&#x1f49e; 算法类别一、算法介绍原理适用的情况做题步骤二…...

enable_if模板编程实现字节序转换模板

enable_if和SFINAESFINAE是模板的一个特性&#xff0c;也就是替换失败不报错。正常来说&#xff0c;函数匹配的时候按照优先级依次匹配定义的重载函数&#xff0c;最终选择最佳匹配的函数运行。模板也是一样的&#xff0c;但是在替换模板时&#xff0c;即使出现异常错误也不认为…...

【人工智能与深度学习】基于能量的模型

【人工智能与深度学习】基于能量的模型 概述能量基础模型(EBM)方法定义解决方案:基于梯度的推理有潜在变量的能量基础模型推理例子能量基础模型和机率模型的对比自由能(Free Energy)概述 我们现在介绍一个新框架来定义模型。它提供了一个统一和系列性的方式来定义「监督模型」…...

功能测试三年,是应该改变了

前言 测试行业3年多经验&#xff0c;学历大专自考本科&#xff0c;主要测试方向web&#xff0c;PC端&#xff0c;wap站&#xff0c;小程序公众号都测试过&#xff0c;app也测过一些&#xff0c;C端B端都有&#xff0c;除功能外&#xff0c;接口性能也有涉猎&#xff0c;但是不…...

基于STM32的ubuntu交叉编译环境的搭建(arm-gcc 8.2)

常用的STM32的软件开发方法都是基于MDK keil或IAR集成开发环境&#xff0c;但以上两个集成开发环境软件都是需要收费的&#xff0c;且价格较为昂贵。本节介绍一种在ubuntu上安装arm gcc&#xff08;arm-eabi&#xff09;的方式&#xff0c;用于编译STM32的程序。 1.在arm官网下…...

数据结构:二叉树概念篇(算法基础)

目录 一.有向树的图论基础 1.有向树的相关基本概念 有向树的基本定义: 有向树的结点的度&#xff1a; 有向树的度: 有向树的根结点,分枝结点,叶结点: 树的子树: 树结点的层次: 树的高度: 2.一个基本的数学结论 3.有序有向树 二.数据结构中树的顺序存储结构与链式存…...

华为OD机试真题Java实现【字符串变换最小字符串】真题+解题思路+代码(20222

字符串变换最小字符串 给定一个字符串s,最多只能进行一次变换,返回变换后能得到的最小字符串(按照字典序进行比较)。 变换规则:交换字符串中任意两个不同位置的字符。 🔥🔥🔥🔥🔥👉👉👉👉👉👉 华为OD机试(Java)真题目录汇总 ## 输入输出描述: …...

数字化转型的企业会用低代码平台深化重塑什么形态

随着数字化转型的浪潮不断推进&#xff0c;越来越多的企业开始关注如何更好地利用数字技术提高业务效率和创新能力。而低代码平台作为一种能够快速构建和部署应用程序的新型工具&#xff0c;正越来越受到企业的青睐。那么&#xff0c;数字化转型的企业会用低代码平台深化重塑什…...

【华为OD机试模拟题】用 C++ 实现 - 拼接 URL(2023.Q1)

最近更新的博客 华为OD机试 - 入栈出栈(C++) | 附带编码思路 【2023】 华为OD机试 - 箱子之形摆放(C++) | 附带编码思路 【2023】 华为OD机试 - 简易内存池 2(C++) | 附带编码思路 【2023】 华为OD机试 - 第 N 个排列(C++) | 附带编码思路 【2023】 华为OD机试 - 考古…...

六千字让你明白什么是数字孪生?

文章目录1. 背景2. 数字孪生基础2.1 概念2.2 价值3. 技术生态3.1 技术体系3.2 核心技术3.2.1 多领域、多尺度融合建模3.2.2 数据驱动与物理模型融合的状态评估3.2.3 数据采集和传输3.2.4 全生命周期数据管理3.2.5 虚拟现实呈现3.2.6 高性能计算3.3 建设3.3.1 重点3.3.1.1 数字孪…...

判断字符串是否是纯数字不包括符号(含符号显示False)isnumeric()和isdigit()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 判断字符串是否是纯数字 不包括符号&#xff08;含符号显示False&#xff09; isnumeric()和isdigit() [太阳]选择题 对于代码中当s为‘二十六’时isdigit()和isnumeric()输出的结果是? s …...

计算机408考研先导课---C语言难点2

目录 一、字符型数据与字符串型数据的比较 1、字符型数据特点 2、字符串型数据特点 二、字符数组 1、定义 2、输入输出 ①输入 ②输出 3、字符处理函数 ①put函数 ②gets函数 ③strcat函数 ④strcpy函数 ⑤strcmp函数 ⑥strlen函数 ⑦strlwr函数 ⑧strup…...

682. 棒球比赛

题目&#xff1a;你现在是一场采用特殊赛制棒球比赛的记录员。这场比赛由若干回合组成&#xff0c;过去几回合的得分可能会影响以后几回合的得分。 比赛开始时&#xff0c;记录是空白的。你会得到一个记录操作的字符串列表 ops&#xff0c;其中 ops[i] 是你需要记录的第 i 项操…...

【《C Primer Plus》读书笔记】第13章:文件输入/输出

【《C Primer Plus》读书笔记】第13章&#xff1a;文件输入/输出13.1 与文件进行通信13.1.1 文件是什么13.1.2 文本模式和二进制模式13.1.3 I/O的级别13.1.4 标准文件13.2 标准I/O13.3 一个简单的文件压缩程序13.4 文件I/O&#xff1a;fprintf()、fscanf()、fgets()和fputs()13…...

Datacom-HCIE考试经验分享

我是誉天Datacom秦同学。作为誉天众多通过Datacom-HCIE考试的学员之一&#xff0c;我感到很荣幸。 首先说说自学的感受吧&#xff1a; 我是从2020年开始接触网络行业的&#xff0c;听单位的前辈说华为的HCIE认证是行业含金量最高的证书&#xff0c;从那时起心里就种下了一个“I…...

第十二章 系统错误消息 - 一般系统错误消息 P - S

文章目录第十二章 系统错误消息 - 一般系统错误消息 P - S第十二章 系统错误消息 - 一般系统错误消息 P - S 错误代码描述<PARAMETER>由用户编写的函数引用或 Do 命令传递给标记行的参数数量超过了为标记行声明的形式参数的数量。<PRIVATE METHOD>已尝试调用一个私…...

【git】Idea中git的使用

配置git 创建git仓库 不同颜色代表的含义 红色——未加入版本控制&#xff1b;绿色——已经加入控制暂未提交&#xff1b;蓝色——加入&#xff0c;已提交&#xff0c;有改动&#xff1b;白色——加入&#xff0c;已提交&#xff0c;无改动&#xff1b;灰色——版本控制已忽略文…...

Centos安装Python、PyCharm

安装Python 1、打开终端(Terminal) 2、输入以下命令更新系统&#xff1a; sudo yum update 3、安装Python&#xff1a; sudo yum install python3 4、安装完成后&#xff0c;可以使用以下命令检查Python版本&#xff1a; python3 --version 安装PyCharm 1、下载PyCharm的安…...