探索数据结构:深入了解顺序表的奥秘
✨✨ 欢迎大家来到贝蒂大讲堂✨✨🎈🎈养成好习惯,先赞后看哦~🎈🎈
所属专栏:数据结构与算法
贝蒂的主页:Betty’s blog
1. 什么是顺序表
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,它与数组非常类似,但是相比于数组顺序表有一个非常明显的优点——可以动态内存增长空间大小

2. 顺序表的功能
顺序表可以大致包含以下几个功能:
初始化顺序表中的数据。
打印顺序表中的数据。
对顺序表进行尾插(末尾插入数据)。
对顺序表进行尾删(末尾删除数据)。
对顺序表进行头插(开头插入数据)。
对顺序表进行头删(开头删除数据)。
对顺序表就像查找数据。
对顺序表数据进行修改。
任意位置的删除和插入数据。
销毁顺序表。
3. 顺序表的定义
定义顺序表我们首先需要一个动态内存开辟的空间,当前数据的个数(size),以及方便扩容的容量大小(capacity)。
typedef int SLDataType; //类型重命名,方便后续修改类型
#define N 4 //初始化空间大小
typedef struct SeqList
{SLDataType* a; //指向动态开辟的数组size_t size; //有效数据个数size_t capacity; //容量大小
}SeqList;
4. 功能的具体实现
4.1 初始化顺序表
(1) 代码实现
初始化顺序表时我们可以先开辟四个空间,之后不够再进行扩容。
void SeqListInit(SeqList* p)
{assert(p); //断言p->a =(SLDataType*)malloc(N*sizeof(SLDataType)); //初始顺序表为四个空间if (p->a== NULL){perror("malloc fail:");return ;}p->size = 0; //初始数据个数为0p->capacity = 4; //初始空间容量为4
}
(2) 复杂度分析
- 时间复杂度:由于没有其他未知数的引入,所以所需时间是个常数,也就是O(1)。
- 空间复杂度:动态开辟N个空间,所以空间复杂度为O(N)。
4.2 打印数据
(1) 代码实现
打印数据只用循环打印就可以了。
void SeqListPrint(const SeqList* p)
{assert(p); //断言if (p->size == 0) //判断顺序表是否为空{printf("顺序表为空\n");return;}int i = 0;for (i = 0; i < p->size; i++) //打印顺序表{printf("%d ", p->a[i]);}printf("\n");
}
(2) 复杂度分析
- 时间复杂度:因为会打印顺序表中的所有数据,所以时间复杂度为O(N)。
- 空间复杂度:打印顺序表并不需要开辟格外的空间,所以空间复杂度为O(1)。
4.3 尾插数据
尾插数据,顾名思义就是在顺序表末尾插入数据,在插入数据之前我们应该检查顺序表是否为满。

(1) 检查是否已满
void CheckCapacity(SeqList* p)
{assert(p); //断言if (p->size == p->capacity) //检查容量,满了则增容{size_t newcapacity = 2 * p->capacity; //,扩容为原来的2倍SLDataType* prt = (SLDataType*)realloc(p->a, newcapacity * sizeof(SLDataType)); //扩容if (prt == NULL){perror("realloc fail:");return ;}p->a = prt; // prt不为空,开辟成功p->capacity = newcapacity; //更新容量}
}
(2) 插入数据
void SeqListPushBack(SeqList* p, SLDataType x)
{assert(p); //断言CheckCapacity(p); //检查顺序表容量是否已满p->a[p->size] = x; //尾插数据p->size++; //有效数据个数+1
}
(3) 复杂度分析
- 时间复杂度:没有变量影响时间,时间复杂度为O(1)。
- 空间复杂度:以最坏的情况考虑,会进行扩容,空间复杂度为O(N)。
4.4 尾删数据
同理,尾删数据就是删除顺序表中最后一个元素,我们只需将size–。注意:删除之前要保证顺序表中有数据。

(1) 代码实现
void SeqListPopBack(SeqList* p)
{assert(p); //断言assert(p->size > 0); //顺序表不能为空p->size--; //有效数据个数-1
}
(2) 复杂度分析
- 时间复杂度:没有变量影响时间,时间复杂度为O(1)。
- 空间复杂度:没有变量影响空间,空间复杂度为O(1)。
4.5 头插数据
头部插入数据就是在第一个元素位置插入一个元素。

(1) 代码实现
void SeqListPushFront(SeqList* p, SLDataType x)
{assert(p); //断言CheckCapacity(p); //检查顺序表容量是否已满int i = 0;for (i = p->size - 1; i >= 0; i--) //顺序表中[0,size-1]的元素依次向后挪动一位{p->a[i + 1] = p->a[i];}p->a[0] = x; //头插数据p->size++; //有效数据个数+1
}
(2) 复杂度分析
- 时间复杂度:因为从头部插入数据,后续数据需要依次覆盖,所以时间复杂度为O(N)。
- 空间复杂度:因为可能会进行扩容,按最坏的情况来算,空间复杂度为O(N)。
4.5 头删数据
从头部删除数据,与尾部删除数据不同,需要依次往前覆盖。

(1) 代码实现
void SeqListPopFront(SeqList* p)
{assert(p); //断言assert(p->size > 0); //顺序表不能为空int i = 0;for (i = 1; i < p->size; i++) //顺序表中[1,size-1]的元素依次向前挪动一位{p->a[i - 1] = p->a[i];}p->size--; //有效数据个数-1
}
(2) 复杂度分析
- 时间复杂度:因为需要往前覆盖数据,所以时间复杂度自然为O(N)。
- 空间复杂度:因为并没有开辟其他空间,所以空间复杂度为O(1)。
4.6 查找指定值
根据输入参数,在顺序表中查找指定的值并返回其下标,若未找到则返回-1。
(1) 代码实现
int SeqListFind(const SeqList* p, SLDataType x)
{assert(p); //断言int i = 0;for (i = 0; i < p->size; i++){if (p->a[i] == x){return i; //查找到,返回该值在数组中的下标}}return -1; //没有查找到
}
(2) 复杂度分析
- 时间复杂度:以最坏的情况分析,时间复杂度为O(N)。
- 空间复杂度:并没有格外的空间消耗,空间复杂度为O(1)。
4.7 指定位置修改
我们可以通过指定下标或者查找指定值的下标来修改任意位置的值。

(1) 代码实现
void SeqListModify(SeqList* p, int pos, SLDataType x)
{assert(p); //断言assert(p->size > 0); //顺序表不能为空assert(pos >= 0 && pos < p->size); //检查pos下标的合法性p->a[pos] = x; //修改pos下标处对应的数据
}
(2) 复杂度分析
- 时间复杂度:因为是通过指定下标修改,所以时间复杂度为O(1)。
- 空间复杂度:没有开辟额外的空间,所以空间复杂度为O(1)。
4.8 指定位置插入
和前面其他插入一样,指定位置插入也需要判断是否扩容。

(1) 代码实现
void SeqListInsert(SeqList* p, int pos, SLDataType x)
{assert(p);//断言assert(pos <= p->size); //检查pos下标的合法性SeqListCheck(p);//扩容int cur = p->size;while (cur > pos){p->a[cur] = p->a[cur - 1];//覆盖--cur;}p->a[pos] = x;p->size++;
}
(2) 复杂度分析
- 时间复杂度:需要依次覆盖,时间复杂度为O(N)。
- 空间复杂度:可能需要扩容,空间复杂度为O(N)。
4.9 指定位置删除
和前面的删除差不多,但是指定删除可能会依次覆盖。

(1) 代码实现
void SeqListErase(SeqList* p, int pos)
{assert(p); //断言assert(p->size > 0); //顺序表不能为空assert(pos >= 0 && pos < p->size); //检查pos下标的合法性int i = 0;for (i = pos + 1; i < p->size; i++) //将pos位置后面的数据依次向前挪动一位{p->a[i - 1] = p->a[i];}p->size--; //有效数据个数-1
}
(2) 复杂度分析
- 时间复杂度:需要依次覆盖,时间复杂度为O(N)。
- 空间复杂度:没有额外的空间消耗,空间复杂度为O(1)。
4.10 回收空间
在结束操作之后,需要释放开辟的空间,以防止内存泄漏。
(1) 代码实现
void SeqListDestory(SeqList* p)
{assert(p); //断言free(p->a); //释放动态开辟的空间p->a = NULL; //置空p->size = 0; //数据个数置0p->capacity = 0; //空间容量大小置0
}
(2) 复杂度分析
- 时间复杂度:没有额外的时间消耗,时间复杂度为O(1)。
- 空间复杂度:没有额外的空间消耗,空间复杂度为O(1)。
5. 完整代码
5.1 SeqList.h
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#define N 4 //初始化空间大小
typedef int SLDataType; //类型重命名,方便后续修改类型
typedef struct SeqList
{SLDataType* a; //指向动态开辟的数组size_t size; //有效数据个数size_t capacity; //容量大小
}SeqList;void SeqListInit(SeqList* p);//初始化顺序表
void SeqListPrint(const SeqList* p);//打印顺序表
void SeqListPushBack(SeqList* p, SLDataType x);//尾插
void SeqListPopBack(SeqList* p);//尾删
void SeqListPushFront(SeqList* p, SLDataType x);//头插
void SeqListPopFront(SeqList* p);//头删
int SeqListFind(const SeqList* p, SLDataType x);//查找数据
void SeqListModify(SeqList* p, int pos, SLDataType x);//修改数据
void SeqListInsert(SeqList* p, int pos, SLDataType x);//指定插入
void SeqListErase(SeqList* p, int pos);//指定删除
void SeqListDestory(SeqList* p);//释放空间
5.2 SeqList.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"
void SeqListInit(SeqList* p)
{assert(p); //断言p->a =(SLDataType*)malloc(N*sizeof(SLDataType)); //初始顺序表为四个空间if (p->a == NULL){perror("malloc fail:");return ;}p->size = 0; //初始数据个数为0p->capacity = 4; //初始空间容量为4
}
void CheckCapacity(SeqList* p)
{assert(p); //断言if (p->size == p->capacity) //检查容量,满了则增容{size_t newcapacity = 2 * p->capacity; //,扩容为原来的2倍SLDataType* prt = (SLDataType*)realloc(p->a, newcapacity * sizeof(SLDataType)); //扩容if (prt == NULL){perror("realloc");return ;}p->a = prt; // prt不为空,开辟成功p->capacity = newcapacity; //更新容量}
}
void SeqListPushBack(SeqList* p, SLDataType x)
{assert(p); //断言CheckCapacity(p); //检查顺序表容量是否已满p->a[p->size] = x; //尾插数据p->size++; //有效数据个数+1
}
void SeqListPrint(const SeqList* p)
{assert(p); //断言if (p->size == 0) //判断顺序表是否为空{printf("顺序表为空\n");return;}int i = 0;for (i = 0; i < p->size; i++) //打印顺序表{printf("%d ", p->a[i]);}printf("\n");
}
void SeqListPopBack(SeqList* p)
{assert(p); //断言assert(p->size > 0); //顺序表不能为空p->size--; //有效数据个数-1
}
void SeqListPushFront(SeqList* p, SLDataType x)
{assert(p); //断言CheckCapacity(p); //检查顺序表容量是否已满int i = 0;for (i = p->size - 1; i >= 0; i--) //顺序表中[0,size-1]的元素依次向后挪动一位{p->a[i + 1] = p->a[i];}p->a[0] = x; //头插数据p->size++; //有效数据个数+1
}
void SeqListPopFront(SeqList* p)
{assert(p); //断言assert(p->size > 0); //顺序表不能为空int i = 0;for (i = 1; i < p->size; i++) //顺序表中[1,size-1]的元素依次向前挪动一位{p->a[i - 1] = p->a[i];}p->size--; //有效数据个数-1
}
int SeqListFind(const SeqList* p, SLDataType x)
{assert(p); //断言int i = 0;for (i = 0; i < p->size; i++){if (p->a[i] == x){return i; //查找到,返回该值在数组中的下标}}return -1; //没有查找到
}
void SeqListModify(SeqList* p, int pos, SLDataType x)
{assert(p); //断言assert(p->size > 0); //顺序表不能为空assert(pos >= 0 && pos < p->size); //检查pos下标的合法性p->a[pos] = x; //修改pos下标处对应的数据
}
void SeqListInsert(SeqList* p, int pos, SLDataType x)
{assert(p);//断言assert(pos <= p->size); //检查pos下标的合法性SeqListCheck(p);//扩容int cur = p->size;while (cur > pos){p->a[cur] = p->a[cur - 1];//覆盖--cur;}p->a[pos] = x;p->size++;
}
void SeqListErase(SeqList* p, int pos)
{assert(p); //断言assert(p->size > 0); //顺序表不能为空assert(pos >= 0 && pos < p->size); //检查pos下标的合法性int i = 0;for (i = pos + 1; i < p->size; i++) //将pos位置后面的数据依次向前挪动一位{p->a[i - 1] = p->a[i];}p->size--; //有效数据个数-1
}
void SeqListDestory(SeqList* p)
{assert(p); //断言free(p->a); //释放动态开辟的空间p->a = NULL; //置空p->size = 0; //数据个数置0p->capacity = 0; //空间容量大小置0
}相关文章:
探索数据结构:深入了解顺序表的奥秘
✨✨ 欢迎大家来到贝蒂大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:数据结构与算法 贝蒂的主页:Betty’s blog 1. 什么是顺序表 顺序表是用一段物理地址连续的存储单元依次存储数据元…...
苍穹外卖学习-----2024/03/010---redis,店铺营业状态设置
1.Redis入门 2.在Java中操作Redis 3.店铺营业状态设置 BUG!!! 今天在启动项目时,用到了Redis缓存数据库,但是却出现了报错信息: ERR Client sent AUTH, but no password is set。Caused by: io.lettuce.core.RedisCommandExecutionException…...
RUST 每日一省:发布到crates.io
github是开源代码分享的地方,rust的开源项目除了github,我们还可以将其发布到 crates.io 上,然后其它用户就可以使用cargo进行安装使用了。其实步骤很简单,只有三条命令了,我们一次来看一下。 1、cargo package 首先&a…...
String类及其常用方法
文章目录 1.String类的特性与使用1.1 String类的特性1.2 String对象的创建方式1.3 String 的使用(不同的拼接操作) 2.String常用方法2.1 String的常用方法一2.2 String常用方法二2.3 String常用方法三 1.String类的特性与使用 1.1 String类的特性 Stri…...
1094. 拼车
说在前面 🎈不知道大家对于算法的学习是一个怎样的心态呢?为了面试还是因为兴趣?不管是出于什么原因,算法学习需要持续保持。 题目描述 车上最初有 capacity 个空座位。车 只能 向一个方向行驶(也就是说,不…...
Docker进阶:深入了解容器数据卷
Docker进阶:深入了解容器数据卷 一、前言二、容器数据卷的作用三、容器数据卷的使用方法四、实战--使用docker部署前端项目(数据卷挂载)4.1 重要:准备工作,先在本地创建挂载目录4.2 启动一个临时的nginx容器࿰…...
升级版本彻底解决bootstrap-table-fixed-columns固定列后行对不齐问题
升级到bootstrap-table和bootstrap-table-fixed-columns版本都升级到v1.22.3版本以上,即可解决该问题 bootstrap-table:bootstrap-table/dist/bootstrap-table.min.css at develop wenzhixin/bootstrap-table GitHub bootstrap-table-fixed-columns&…...
打破边界:深入探索STUN在实现无缝NAT穿越和WebRTC通信中的核心作用
引言 STUN是一个网络协议,设计用于帮助在网络地址转换(NAT)后面的设备发现其公网地址和端口号。通过允许这些设备发现自己从外部看到的地址,STUN使得它们能够在NAT或防火墙背后建立端到端的通信,这对于VoIP、视频会议…...
浅谈 前端的动态绑定属性
目录 前言1. 基本知识2. Demo 前言 作为Java开发者,从开发转到全栈,前端好些细节都需要科普,这不就来个动态绑定属性 起因是这个: <uni-tr> <uni-td align"center" :rowspan"checkTypesCount 1"…...
Sklearn支持向量机
支持向量机(Support Vector Machine, SVM)是一种常用的分类算法,它可以用于解决二分类和多分类问题。在Python中,你可以使用Sklearn库来实现SVM。下面是一个简单的例子,展示了如何使用Sklearn进行SVM分类。 # 导入必要…...
【Lazy ORM】 小工具 acw 本地客户端 你负责点击页面,他负责输出代码
介绍 wu-smart-acw-client 简称acw-client,是一个基于Lazy ORM定制的客户端代码生成小工具 Lazy ORM 小工具 acw 本地客户端 你负责点击页面,他负责输出代码安装 <dependency><groupId>top.wu2020</groupId><artifactId>wu-sma…...
《详解:鸿蒙NEXT开发核心技术》
我们现在都知道鸿蒙作为一个国产的全栈自研系统,经过国家主推后。已经引起人们很大的关注,其中作为开发者来说;许多一线大厂已经与其华为鸿蒙展开原生应用的合作了,目前了解到已经有200家。而之后出现了很多的高薪鸿蒙开发岗位&am…...
快速排序 刷题笔记
思路 分治双指针 在每个区间选定一个基准目标 两个指针从数组的两边向中间推进 使用 while循环判断 do {i;}while(q[i]<x); do{j--;}while(q[j]>x); 每次这样做完就会找到q[i]>x,,,,q[j]小于x 此时我们交换 q[i] ,q[j]于是小于x的数分到了小于x的一侧 大…...
DAY by DAY 史上最全的Linux常用命令汇总----man
man是按照手册的章节号的顺序进行搜索的。 man设置了如下的功能键: 功能键 功能 空格键 显示手册页的下一屏 Enter键 一次滚动手册页的一行 b 回滚一屏 f 前滚一屏 q 退出man命令 h 列出所有功能键 /word 搜索word字符串 注意:…...
十六、接口隔离原则、反射、依赖注入
接口隔离原则、反射、特性、依赖注入 接口隔离原则 客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。 五种原则当中的i 上一章中的接口,即契约。 契约就是在说两件事,甲方说自己不会多要,乙方会在…...
Docker 进阶
1、容器数据卷 什么是容器数据卷? 就是当容器内存在了mysql,在里面书写了数据,如果容器删除了,那么数据也就没有了,通过容器数据卷的技术,可以让容器内的数据持久化到Linux服务器上 操作 #docker run -…...
科研学习|论文解读——一种修正评分偏差并精细聚类中心的协同过滤推荐算法
知网链接 一种修正评分偏差并精细聚类中心的协同过滤推荐算法 - 中国知网 (cnki.net) 摘要 协同过滤作为国内外学者普遍关注的推荐算法之一,受评分失真和数据稀疏等问题影响,算法推荐效果不尽如人意。为解决上述问题,本文提出了一种改进的聚类…...
云计算项目十一:构建完整的日志分析平台
检查k8s集群环境,master主机操作,确定是ready 启动harbor [rootharbor ~]# cd /usr/local/harbor [rootharbor harbor]# /usr/local/bin/docker-compose up -d 检查head插件是否启动,如果没有,需要启动 [rootes-0001 ~]# system…...
2.经典项目-海量用户即使通讯系统
1.实现功能-完成注册用户 完成用户注册的步骤(客户端) 1.将User移动到common/message文件夹下 2.在message中新增注册用户的结构体 const (LoginMesType "LoginMes"LoginResMesType "LoginResMes"RegisterMesType "RegisterMes"…...
基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的交通标志识别系统详解(深度学习模型+UI界面代码+训练数据集)
摘要:本篇博客详细介绍了利用深度学习构建交通标志识别系统的过程,并提供了完整的实现代码。该系统采用了先进的YOLOv8算法,并与YOLOv7、YOLOv6、YOLOv5等早期版本进行了性能评估对比,分析了性能指标如mAP、F1 Score等。文章深入探…...
PaddlePaddle-v3.3新手入门:Jupyter+SSH双模式,开箱即用深度学习环境
PaddlePaddle-v3.3新手入门:JupyterSSH双模式,开箱即用深度学习环境 1. 为什么选择PaddlePaddle-v3.3镜像 深度学习环境配置一直是AI开发者面临的第一道门槛。不同框架版本、CUDA版本、Python包依赖之间的兼容性问题常常让人头疼不已。PaddlePaddle-v3…...
手把手教你用Python复刻‘双紫擒龙’量化指标(附完整源码与回测)
手把手教你用Python复刻‘双紫擒龙’量化指标(附完整源码与回测) 在量化交易领域,技术指标的神秘面纱常常让初学者望而却步。今天,我们将用Python彻底拆解这个名为"双紫擒龙"的指标,从数据获取到可视化回测&…...
网站推广seo优化公司如何提高网站转化率
网站推广seo优化公司如何提高网站转化率 在当今数字化时代,网站的转化率直接关系到一个企业的成功与否。高转化率意味着更多的访客将成为潜在客户,进而成为实际的客户。对于网站推广seo优化公司而言,如何有效提高网站转化率是其核心业务之一…...
OpenClaw备份自动化:用SecGPT-14B识别关键数据并同步加密
OpenClaw备份自动化:用SecGPT-14B识别关键数据并同步加密 1. 为什么需要智能备份系统 作为一个长期在本地开发项目的程序员,我经历过太多次"误删文件后追悔莫及"的时刻。传统的定时全量备份虽然简单,但存在三个致命问题ÿ…...
vue高频八股
一、基础知识:1.二、指令:概念:带有v-前缀的特殊html属性,用于在模板中表达逻辑,用于将响应式数据绑定到 DOM 元素上或在 DOM 元素上进行一些操作。1.v-if和v-show有什么区别:(1)v -…...
C语言void指针详解与应用实践
1. 理解void指针的本质在C语言中,void指针(void *)是一种特殊类型的指针,它被称为"通用指针"或"无类型指针"。与普通指针不同,void指针不关联任何具体的数据类型,这使得它具有独特的特性和用途。1.1 void指针…...
K8s网络策略深度实验:用NetworkPolicy实现微服务隔离(含Calico实战)
K8s网络策略深度实验:用NetworkPolicy实现微服务隔离(含Calico实战) 在云原生架构中,微服务间的网络隔离是安全工程师必须掌握的核心技能。当多个租户或业务线共享同一个Kubernetes集群时,不加控制的Pod间通信可能引发…...
DBA必看:Oracle OCP认证到底值不值得考?2024年最新薪资与职业发展分析
Oracle OCP认证2024深度评测:从薪资数据到职业跃迁的实战指南 在数据库技术领域,Oracle始终占据着不可撼动的地位。每当我在技术社区看到年轻DBA们关于职业认证的讨论,总会被问到同一个问题:"Oracle OCP认证在2024年还值得投…...
2025届毕业生推荐的AI科研平台推荐榜单
Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 使AIGC检测率得以降低的关键所在是去削弱文本具备的规律性以及模式化特性。具体的策略涵盖这…...
得意黑Smiley Sans字体高效部署实战指南
得意黑Smiley Sans字体高效部署实战指南 【免费下载链接】smiley-sans 得意黑 Smiley Sans:一款在人文观感和几何特征中寻找平衡的中文黑体 项目地址: https://gitcode.com/gh_mirrors/smi/smiley-sans 作为一款在人文观感和几何特征中寻找平衡的现代中文黑体…...

