数据结构—顺序表
目录
1.线性表
2.顺序表概念
3.实现顺序表
(1)声明结构体
(2)初始化
(3)打印数据
(4) 销毁
(5)尾插&头插
尾插
判断是否扩容
头插
(6)尾删&头删
尾删
头删
(7)指定位置插入元素
(8)删除指定位置元素
(9)查找指定元素位置
(10)修改指定位置元素
完整版附上:
Seqlist.h
text.c
Seqlist.c
1.线性表
- 线性表是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...
- 线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,
- 线性表在物理上存储时,通常以数组和链式结构的形式存储。
2.顺序表概念
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。
2. 动态顺序表:使用动态开辟的数组存储。

3.实现顺序表
静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用。所以现实中基本都是使用 动态顺序表 ,根据需要动态的分配空间大小,所以下面我们实现动态顺序表。
我们创建三个文件:
- Seqlist.h用于存放头文件、结构体和函数的声明
- text.c作为主程序进行运行和测试
- Seqlist.c存放函数主体
(1)声明结构体
#include <stdio.h>typedef int SLDatatype;
typedef struct SeqList
{SLDatatype* a;int size;int capacity;
}SL;
- 在头文件中声明结构体struct SeqList,由于名字太长,我们用typedef自定义结构体名称的别名为SL。
- 将顺序表的数据类型用SLDatatype这个别名代替int,以后程序中使用到元素数据类型时都替换成SLDatatype,方便日后修改顺序表数据类型。
- 定义size存储当前元素个数,capacity存储顺序表容量。
(2)初始化
void SLInit(SL* psl)
{assert(psl);psl->a = (SLDatatype*)malloc(sizeof(SLDatatype) * 4);if (psl->a == NULL) {perror("malloc fail");return;}psl->size = 0;psl->capacity = 4;
}
- 需要改变结构体变量,则将其地址传入函数。
- assert检测传参顺序表指针是否合法,如果传入参数为空则报错(具体哪行出错)。
- 然后为结构体成员a分配4个成员类型空间,顺便检查是否分配成功。
- 对成员size和capacity分别复制为0(当前元素个数)和4(顺序表容量)。
(3)打印数据
void SLPrint(SL* psl)
{assert(psl);for (int i = 0; i < psl->size; i++) {printf("%d ", psl->a[i]);}
}
- assert检测传参顺序表指针是否合法,然后循环遍历输出。
(4) 销毁
void SLDestroy(SL* psl)
{assert(psl);free(psl->a);psl->a = NULL;psl->size = 0;psl->capacity = 0;
}
- assert检测传参顺序表指针是否合法。
- 释放动态开辟a的空间,同时赋值为空,不置空可能会造成野指针的访问。
- size和capacity分别赋值为0。
(5)尾插&头插
尾插
void SLPushBack(SL* psl, SLDatatype x)
{assert(psl);SLCheckCapacity(psl);psl->a[psl->size] = x;psl->size++;
}
- assert检测传参顺序表指针是否合法。
- 判断数组是否已经装满,如果装满则进行扩容,这些操作我们在函数SLCheckCapacity内进行。
- 将
x赋值给psl->a数组中下一个可用的位置,即psl->size索引处。 - 递增
psl->size,以便记录新元素的加入。
接下来我们来讲解函数SLCheckCapacity:
判断是否扩容
void SLCheckCapacity(SL* psl)
{if (psl->size == psl->capacity) {SLDatatype* tmp = (SLDatatype*)realloc(psl->a, sizeof(SLDatatype) * psl->capacity * 2);if (tmp == NULL) {perror("realloc fail");return;}psl->a = tmp;psl->capacity *= 2;}
}
- 判断当前元素个数size与顺序表容量capacity是否相等,相等则对结构体成员指针a进行扩容。
- 通过realloc函数对a的内存进行扩容,每次增加一倍容量,并将reallocd的返回值新空间的起始地址赋值给SLDatatype类型指针 tmp,这样避免直接对a开辟空间时发生错误丢失数据。
- 检测是否成功扩容。
- 最后将存放新空间地址的tmp赋值给a。
- 顺序表的容量也随之扩大为原来的两倍。
我们还可以优化一下尾插函数,具体如下:
void SLPushBack(SL* psl, SLDatatype x)//尾插
{SLCheckCapacity(psl);psl->a[psl->size++] = x;
}
头插
void SLPushFront(SL* psl, SLDatatype x)
{assert(psl);SLCheckCapacity(psl);int end = psl->size - 1;while (end >= 0) {psl->a[end + 1] = psl->a[end];end--;}psl->a[0] = x;psl->size++;
}
- assert检测传参顺序表指针是否合法。
- 判断数组是否已经装满,如果装满则进行扩容,这些操作在函数SLCheckCapacity内进行。
- 定义end表示当前顺序表中最后一个元素的下标。
- while循环用于从后向前将顺序表中的元素依次向后移动一个位置,为新元素
x腾出空间 - 将新元素
x插入到顺序表的开头 - 顺序表元素个数
size增加1
(6)尾删&头删
尾删
void SLPopBack(SL* psl)
{assert(psl);//暴力判断assert(psl->size == 0);//常规判断//if (psl->size == 0)// return;psl->a[psl->size - 1] = 0;psl->size--;
}
- 第一个assert检测传参顺序表指针是否合法。
- 第二个assert检测顺序表是否为空,为空没有元素则不需要删除,程序报错。
- 我们还可以通过顺序表元素个数判断,if语句判断size为0时,函数停止运行。
- 顺序表大小不为空,则对最后一个元素进行删除,赋值为0。
- 顺序表大小size减1.
头删
void SLPopFront(SL* psl)
{assert(psl);assert(psl->size > 0);int start = 0;while (start < psl->size) {psl->a[start] = psl->a[start + 1];start++;}psl->size--;
}
- 第一个assert检测传参顺序表指针是否合法。
- 第二个assert检测顺序表是否为空,为空没有元素则不需要删除,程序报错。
- 定义变量start为首元素下标.
- 头删不用赋值为0,直接从第一个元素开始后项赋值给前项。
(7)指定位置插入元素
void SLInsert(SL* psl, int pos, SLDatatype x)
{assert(psl);assert(0 <= pos && pos <= psl->size);SLCheckCapacity(psl);int end = psl->size - 1;while (end > 0) {psl->a[end + 1] = psl->a[end];end--;}psl->size++;psl->a[pos] = x;
}
- 参数pos为要在第几个元素后插入。
- 第一个assert检测传参顺序表指针是否合法。
- 第二个assert检测传参pos的位置是否合法。
- 判断数组是否已经装满,如果装满则进行扩容,这些操作在函数SLCheckCapacity内进行。
- 定义end表示当前顺序表中最后一个元素的下标。
- while循环用于从后向前将顺序表中的元素依次向后移动一个位置,为新元素
x腾出空间 - 顺序表元素个数
size增加1。 - 将新元素
x插入到顺序表指定元素位置之后。
SLInsert这个函数可以代替头插尾插函数进行顺序表元素的增加。
(8)删除指定位置元素
void SLErase(SL* psl, int pos)
{assert(psl);assert(0 <= pos && pos <= psl->size);int start = pos + 1;while (start < psl->size) {psl->a[start - 1] = psl->a[start];start++;}psl->size--;
}
- 第一个assert检测传参顺序表指针是否合法。
- 第二个assert检测传参pos的位置是否合法。
- 定义变量start存储pos位置后一项的下标。
- 将删除元素后一项位置的值开始从pos+1向后依次前移一位,顶替pos位置。
- 顺序表元素个数减一。
这个函数就可以完全代替头删尾删了。
(9)查找指定元素位置
int SLFind(SL* psl, SLDatatype x)
{assert(psl);for (int i = 0; i < psl->size; i++) {if (psl->a[i] == x)return i+1;}return -1;
}
- assert检测传参顺序表指针是否合法。
- 循环遍历顺序表找出于x相等的元素,返回其下标。
- 找不到返回-1。
(10)修改指定位置元素
void SLModify(SL* psl, int pos, SLDatatype x)
{assert(psl);assert(0 <= pos && pos <= psl->size);psl->a[pos] = x;
}
- 第一个assert检测传参顺序表指针是否合法。
- 第二个assert检测传参pos的位置是否合法。
-
将pos位置的值修改为x。
完整版附上:
Seqlist.h
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int SLDatatype;
typedef struct SeqList
{SLDatatype* a;int size;int capacity;
}SL;void SLInit(SL* psl);
void SLDestroy(SL* psl);
void SLPrint(SL* psl);
void SLPushBack(SL* psl, SLDatatype x);
void SLPushFront(SL* psl, SLDatatype x);
void SLPopBack(SL* psl);
void SLPopFront(SL* psl);
void SLInsert(SL* psl, int pos, SLDatatype x);
void SLErase(SL* psl, int pos);
int SLFind(SL* psl, SLDatatype x);
void SLModify(SL* psl, int pos, SLDatatype x);
text.c
这里大家可以自行发挥!
#define _CRT_SECURE_NO_WARNINGS 1
#include "Seqlist.h"void test1()
{SL s;SLInit(&s);SLPushBack(&s, 5);SLPushBack(&s, 9);SLPushBack(&s, 50);SLPushFront(&s, 1);SLPushFront(&s, 15);SLPushFront(&s, 0);SLPopBack(&s, 50);SLPopFront(&s, 0);SLInsert(&s, 2, 555);SLErase(&s, 4);SLPrint(&s);int a=SLFind(&s, 15);printf("\n%d\n", a);if (a != -1)SLErase(&s, a);SLPrint(&s);SLDestroy(&s);
}int main()
{test1();return 0;
}
Seqlist.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Seqlist.h"void SLInit(SL* psl)//初始化
{assert(psl);psl->a = (SLDatatype*)malloc(sizeof(SLDatatype) * 4);if (psl->a == NULL) {perror("malloc fail");return;}psl->size = 0;psl->capacity = 4;//每次开辟的容量为四个
}void SLPrint(SL* psl)//打印数据
{assert(psl);for (int i = 0; i < psl->size; i++) {printf("%d ", psl->a[i]);}
}void SLDestroy(SL* psl)//结束使用需要销毁
{assert(psl);free(psl->a);psl->a = NULL;psl->size = 0;psl->capacity = 0;
}void SLCheckCapacity(SL* psl)
{if (psl->size == psl->capacity) {//增加一倍容量SLDatatype* tmp = (SLDatatype*)realloc(psl->a, sizeof(SLDatatype) * psl->capacity * 2);if (tmp == NULL) {perror("realloc fail");return;}psl->a = tmp;psl->capacity *= 2;}}void SLPushBack(SL* psl, SLDatatype x)//尾插
{assert(psl);//psl->a[psl->size] = x;//psl->size++;//插入需要判断a是否已满,已满需要扩容SLCheckCapacity(psl);//或者写成一句psl->a[psl->size++] = x;//后置自增
}void SLPushFront(SL* psl, SLDatatype x)//头插
{assert(psl);SLCheckCapacity(psl);int end = psl->size - 1;while (end >= 0) {psl->a[end + 1] = psl->a[end];end--;}psl->a[0] = x;psl->size++;
}
void SLPopBack(SL* psl)
{assert(psl);//尾删//暴力判断//assert(psl->size == 0);//常规判断if (psl->size == 0)return;psl->a[psl->size - 1] = 0;psl->size--;
}void SLPopFront(SL* psl)//头删
{assert(psl);assert(psl->size > 0);int start = 0;while (start < psl->size) {psl->a[start] = psl->a[start + 1];start++;}psl->size--;
}void SLInsert(SL* psl, int pos, SLDatatype x)//指定位置插入元素,可代替头插尾插
{assert(psl);assert(0 <= pos && pos <= psl->size);//判读插入位置是否合法SLCheckCapacity(psl);int end = psl->size - 1;while (end > 0) {psl->a[end + 1] = psl->a[end];end--;}psl->size++;psl->a[pos] = x;
}void SLErase(SL* psl, int pos)//删除指定位置元素,代替头删尾删
{assert(psl);assert(0 <= pos && pos <= psl->size);int start = pos + 1;while (start < psl->size) {psl->a[start - 1] = psl->a[start];start++;}psl->size--;
}int SLFind(SL* psl, SLDatatype x)//查找指定元素位置
{assert(psl);for (int i = 0; i < psl->size; i++) {if (psl->a[i] == x)return i+1;}return -1;//找不到返回-1
}void SLModify(SL* psl, int pos, SLDatatype x)//修改指定位置元素
{assert(psl);assert(0 <= pos && pos <= psl->size);psl->a[pos] = x;
}
相关文章:
数据结构—顺序表
目录 1.线性表 2.顺序表概念 3.实现顺序表 (1)声明结构体 (2)初始化 (3)打印数据 (4) 销毁 (5)尾插&头插 尾插 判断是否扩容 头插 (6)尾删&头删 尾删 头删 (7)指定位置插入元素 (8)删除指定位置元素 (9)查找指定元素位置 (10)修改指定位置元素 完整版…...
企业服务器租用对性能有什么要求呢?
企业租用服务器租用首要的是稳定,其次是安全,稳定是为了让企业的工作能够顺利进行,只有性能稳定的服务器才能保证网站之类的正常工作,就让小编带大家看一看有什么要求吧! 服务器简单介绍。服务器是在网络上为其它客户机…...
2731.移动机器人
2731. 移动机器人 - 力扣(LeetCode) 有一些机器人分布在一条无限长的数轴上,他们初始坐标用一个下标从 0 开始的整数数组 nums 表示。当你给机器人下达命令时,它们以每秒钟一单位的速度开始移动。 给你一个字符串 s ,…...
相交链表Java
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 nu11。 以下有两种解决方法: 一种是用Map,利用其key值唯一的方法去判断(也可以使用set,set在add时,已存在的元素会返回false,不存在的返回…...
第二章:OSI参考模型与TCP/IP模型
OSI参考模型与TCP/IP模型 一、OSI参考模型二、TCP/IP模型2.1 四层分法(书上)2.2 五层分法(实际厂商)2.3 数据封装和解封装2.3.1 封装2.3.2 解封装2.3.3 TCP/IP分层封装2.3.4 数据封装和解封装过程 一、OSI参考模型 1.物理层 定义电…...
知识图谱04——openGL与ubuntu22.04
跑图神经网络的时候遇到了如下问题 libGL error: failed to load driver: iris libGL error: MESA-LOADER: failed to open iris: /usr/lib/dri/iris_dri.so: 无法打开共享对象文件: 没有那个文件或目录 (search paths /usr/lib/x86_64-linux-gnu/dri:\$${ORIGIN}/dri:/usr/li…...
如何看待为了省小钱而花费时间
相信每个人都会遇到这种情况:购买东西时想着货比三家或者想办法领优惠券、凑单等就可以省下一些钱,但是需要花费不少时间和精力。这时就开始犹豫了:省钱是必要的,需要居安思危,等到缺钱的时候不会后悔;又想…...
Maven Eclipse
Eclipse 提供了一个很好的插件 m2eclipse ,该插件能将 Maven 和 Eclipse 集成在一起。 在最新的 Eclipse 中自带了 Maven,我们打开,Windows->Preferences,如果会出现下面的画面: 下面列出 m2eclipse 的一些特点&a…...
Linux:redis集群(3.*版本 和 5.*版本)搭建方法
介绍 至少6个实例才能组成集群。3主3从会自动分配 Redis集群原理 Redis集群架构 Redis Cluster采用虚拟槽分区,将所有的数据根据算法映射到0~16383整数槽内 Redis Cluster是一个无中心的结构 每个节点都保存数据和整个集群的状态 集群角色 Master:Master…...
正则表达式基础语法
https://tool.oschina.net/regex 正则表达式:检查、匹配字符串的表达式 单个字符匹配: 有特殊含义的匹配: 多次重复匹配: 限定开头结尾的匹配: 贪婪模式:在满足条件的情况下,尽可能多匹配…...
数据库常见面试题--MySQL
梳理面试过程中数据库相关的常见问题,需要说明的是,这篇文章主要是基于MySQL数据库,其他类型的数据库还请自行参考使用。 数据库概述 为什么使用数据库 1、数据库增删改查更方便 2、提供了事务的能力 本质是更好的管理数据。 数据库体系结…...
Springboot 集成 Redis集群配置公网IP连接报私网IP连接失败问题
1、问题:在Springboot 集成 Redis集群配置公网IP连接报私网IP连接失败,一直报私有IP连接失败 14 14:57:49.180 WARN 22012 --- [ioEventLoop-6-4] i.l.c.c.topology.ClusterTopologyRefresh : Unable to connect to [192.168.0.19:6384]: connection …...
解决方案 | 法大大电子签精准击破销售场景签约难题
新商业形态及新交易模式不断涌现,电子签已经成为现代商业活动中不可或缺的一部分。特别是在销售场景中,电子签的应用不仅可以提高销售效率,还可以降低成本,提高客户满意度。本文将详细分析电子签在销售场景中的应用价值能力&#…...
ARM按键中断控制事件
设置按键中断,按键1按下,LED亮,再按一次,灭按键2按下,蜂鸣器响。再按一次,不响按键3按下,风扇转,再按一次,风扇停 src/key_it.c #include"key_it.h" //GPIO初…...
微信小程序之本地生活(九宫格)
文章目录 一.创建项目二.配置修改json三.编写WXML四.编写WXSS五.最终效果 一.创建项目 创建新的项目,名称为:本地生活 二.配置修改json 在app.json中删除其他页面 将index改为grid 自动生成新的文件 添加自己的轮播图片 源代码: <!--…...
【Linux 安装Kibana 及 Es 分词器安装】
一、客户端Kibana安装 Kibana是一个开源分析和可视化平台,旨在与Elasticsearch协同工作。参考文档 1. 下载并解压缩Kibana 下载路径 选择的版本是和 ElasticSearch 对应(7.17.3) 下载后上传到Linux 系统中,并放在 /root/ 下&a…...
python-arima模型statsmodels库实现-有数据集(续)-statsmodels-0.9.0版本
python-arima模型statsmodels库实现-有数据集(续) 这篇博客是上一篇python-arima模型statsmodels库实现的续集,上一篇采用的statsmodels版本应该要高一点,如果使用低版本的statsmodels代码会有bug,这一篇则是针对stat…...
JVM源码剖析之线程的创建过程
说在前面: 对于Java线程的创建这个话题,似乎已经被"八股文"带偏~ 大部分Java程序员从"八股文"得知创建Java线程有N种方式,比如new Thread、new Runnable、Callable、线程池等等~ 而笔者写下这篇文…...
ansible的介绍安装与模块
目录 一、ansible简介 二、ansible特点 三、Ansible核心组件与工作原理 1、核心组件 2、工作原理 四、ansible的安装 五、ansible 命令行模块 1.command 模块 2.shell 模块 3.cron 模块 4.user 模块 5.group 模…...
el-form简单封装一个列表页中的搜索栏
父组件如何使用 代码中注释很多, 应该很容易理解 <template><div><wgySearchv-model"searchDefault":fields"searchFields"reset"reset"submit"submit"><!-- 通过 slot 自定义的组件 传啥都行 --><te…...
AI对话记忆管理实战:memory-organizer库解决长上下文难题
1. 项目概述:一个为AI记忆体“瘦身”与“归档”的利器最近在折腾一些本地大语言模型(LLM)的应用,比如搭建个人知识库助手或者长期对话机器人,一个绕不开的痛点就是“记忆”的管理。模型本身没有持久记忆,每…...
FastAPI快速入门:环境搭建+第一个接口
FastAPI快速入门:环境搭建第一个接口文章信息 标题:FastAPI快速入门:环境搭建第一个接口字数:4200字预估阅读时间:18分钟难度:⭐☆☆☆☆一、为什么选择FastAPI? 在2026年的Python Web框架生态中…...
VIBESRAILS:基于Rails的音视频智能分析后端框架实践指南
1. 项目概述与核心价值最近在折腾一个挺有意思的开源项目,叫 VIBESRAILS,来自 GitHub 上的 VictoHughes 仓库。乍一看这个名字,可能有点摸不着头脑,但如果你对音视频处理、实时通信或者多媒体分析有点兴趣,那这个项目绝…...
告别3D-DNA的卡顿:用Chromap+Yahs快速搞定植物Hi-C辅助组装(附完整代码)
植物基因组Hi-C辅助组装新方案:ChromapYahs全流程解析 在植物基因组研究中,Hi-C技术已成为提升组装连续性的重要手段。然而传统3D-DNA流程在植物数据上的表现常令研究者头疼——运行速度缓慢、内存占用高,且对植物特有的重复序列处理效果欠佳…...
跨越平台鸿沟:Simulink、VeriStand与LabVIEW联合仿真环境一站式部署指南
1. 为什么需要联合仿真环境? 在工业自动化和科研领域,我们经常遇到一个尴尬的局面:不同团队使用的工具链完全不同。控制算法工程师习惯用Simulink建模,测试工程师依赖LabVIEW开发上位机,而硬件在环(HIL&am…...
Nuxt.js Tailwind CSS 模块:零配置快速启动现代Web开发
Nuxt.js Tailwind CSS 模块:零配置快速启动现代Web开发 【免费下载链接】tailwindcss Tailwind CSS module for Nuxt 项目地址: https://gitcode.com/gh_mirrors/tai/tailwindcss Nuxt.js Tailwind CSS 模块是一个专为Nuxt框架设计的Tailwind CSS集成解决方案…...
3DS文件传输终极解决方案:告别命令行,轻松无线推送游戏文件
3DS文件传输终极解决方案:告别命令行,轻松无线推送游戏文件 【免费下载链接】3DS-FBI-Link Mac app to graphically push CIAs to FBI. Extra features over servefiles and Boop. 项目地址: https://gitcode.com/gh_mirrors/3d/3DS-FBI-Link 对于…...
ARM GICv3虚拟中断控制器架构与ICV_CTLR_EL1寄存器解析
1. ARM GICv3虚拟中断控制器架构概述在ARMv8-A架构的虚拟化环境中,GICv3中断控制器通过引入虚拟CPU接口寄存器组,为虚拟机提供了与原生物理中断处理机制高度一致的虚拟中断体验。这套虚拟寄存器组与物理寄存器组采用相同的编程模型,但在访问控…...
破解软件安全计划人才困局:从安全左移到DevSecOps实践
1. 软件安全计划(SSI)的困境与破局:从一份调查报告说起 最近,一份由新思科技(Synopsys)在中国市场发起的调查报告,在不少技术管理者的圈子里引发了讨论。报告里一个刺眼的数字是: 6…...
安卓手机缓存视频救星:手把手教你将腾讯课堂的.m3u8.sqlite文件转成MP4
安卓手机腾讯课堂缓存视频解密实战:从.m3u8.sqlite到MP4全流程指南 你是否曾在腾讯课堂APP下载了付费课程,却发现缓存文件是一堆无法直接播放的.m3u8.sqlite格式?这些加密文件既不能备份到电脑,也无法在其他设备上观看。本文将彻底…...
