初级数据结构(一)——顺序表
| 文中代码源文件已上传:数据结构源码 <-上一篇 NULL | 初级数据结构(二)——链表 下一篇-> |
1、顺序表的特点
1.1、数组
现实中数据记录一般都记录在表格中,如进货单、菜单等,它们的最大特点就是有序。表述中可以用第一项、第二项、第 n 项来描述表格中某个数据或者某串数据。在 C 语言中,数组的特点恰好匹配此功能。
由于数组在内存中的储存方式就如同列表依序排布,对数组可以用 arr[n] 或者 *(arr+n) 来迅速获得第 n-1 项数据。再加上而且数组是 C 语言的原生类型,创建数组极其便利,作为有序数据的载体着实是不二之选。
1.2、结构
顺序表为了方便使用,除了用数组作为数据载体外,一般还包含记录数组空间大小和开辟空间大小的两个变量。常以结构体将这三个变量作为成员变量进行囊括。主要有两种创建方式:
柔性数组顺序表( Sequence table with flexible array ):

#include <stdlib.h>//重定义数据类型
typedef int DATA;//创建并重定义结构体类型
typedef struct SeqTab
{int size; //数据长度int capacity; //数据空间大小DATA arr[]; //数据载体柔性数组
}SeqTab;int main()
{//开辟结构体空间SeqTab* sqList = (SeqTab*)malloc(sizeof(SeqTab) + sizeof(DATA)*4);//初始化数据长度及空间大小sqList->size = 0;sqList->capacity = 4;return 0;
}
数组指针顺序表( Sequence table with array pointer ):

#include <stdlib.h>//重定义数据类型
typedef int DATA;//创建并重定义结构体类型
typedef struct SeqTab
{int size; //数据长度int capacity; //数据空间大小DATA* arr; //数据载体数组指针
}SeqTab;int main()
{//创建结构体变量SeqTab sqList;//开辟数据载体数组空间sqList.arr = (DATA*)malloc(sizeof(DATA)*4);//初始化数据长度及空间大小sqList.size = 0;sqList.capacity = 4;return 0;
}
2、顺序表创建
接下来以数组指针顺序表为例进行演示。
2.1、文件结构

seqTab.h :用于创建结构体类型及声明函数;
sqFunction.c :用于创建顺序表初始化及增删改查的函数;
main.c :仅创建 main 函数,用作测试。
2.2、前期工作
在 seqTab.h 中先写入以下内容:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>//用于初始化顺序表时开辟空间
#define INIT_SIZE 4//顺序表数据类型,方便顺序表储存数据类型修改
typedef int DATATYPE;//创建顺序表结构体类型
typedef struct SeqTab
{DATATYPE* data;int size;int capacity;
}SeqTab;//---------------------函数声明---------------------
//初始化顺序表
extern void DataInit(SeqTab*);//销毁顺序表
extern void DataDestory(SeqTab*);//打印顺序表
extern void DataPrint(const SeqTab*);
在 sqFunction.c 中包含 seqTab.h 并分别创建一个初始化顺序表和销毁顺序表的函数:
#include "seqTab.h"//初始化顺序表
void DataInit(SeqTab* sq)
{//断言确保结构体指针不为空assert(sq);//为顺序表开辟空间sq->data = (DATATYPE*)malloc(INIT_SIZE * sizeof(DATATYPE));//加入判断防止空间开辟失败if (sq->data == NULL){perror("Malloc Fail");return;}//初始化记录数据长度及开辟空间长度的变量sq->size = 0;sq->capacity = INIT_SIZE;
}//销毁顺序表
void DataDestory(SeqTab* sq)
{//断言确保结构体指针不为空assert(sq);//释放顺序表数据空间free(sq->data);//数组指针置空sq->data = NULL;//数组长度及空间尺寸全部置0sq->size = 0;sq->capacity = 0;
}//打印顺序表
void DataPrint(const SeqTab* sq)
{//断言确保结构体指针不为空assert(sq);//遍历顺序表并逐个数据打印for (int i = 0; i < sq->size; i++){printf("%d ", sq->data[i]);}printf("\n");
}
最后在 main.c 中包含 seqTab.h,并创建一个顺序表及初始化:
#include "seqTab.h"int main()
{//创建顺序表SeqTab sqList;//初始化顺序表DataInit(&sqList);return 0;
}
至此,前期工作准备完毕,之后便是对顺序表的数据进行增删改查。
3、顺序表操作
3.1、增
插入数据一般为头部插入数据、尾部插入数据及指定位置插入数据。插入数据时除了写入数据到数组中,还需时刻判断开辟的空间尺寸是否足以容纳已有数据。
先将以下三个函数声明添加到 seqTab.h 中:
//指定位置插入数据
extern void DataInsert(SeqTab*, int, DATATYPE);
//头部插入数据
extern void DataPushHead(SeqTab*, DATATYPE);
//尾部插入数据
extern void DataPushTail(SeqTab*, DATATYPE);
然后便是 DataInsert 函数。如图:

据此可以轻松写出其代码。以下写入 sqFunction.c 中:
void DataInsert(SeqTab* sq, int pos, DATATYPE data)
{//数据有效性判断assert(sq);if (pos < 0 || pos > sq->size){printf("Illegal Position : %d\n", pos);return;}//空间不足则创建空间if (sq->size + 1 >= sq->capacity){//申请新空间DATATYPE* ptr_newSqData = (DATATYPE*)realloc(sq->data, sizeof(DATATYPE) * (sq->capacity * 2));//空间申请结果判断if (ptr_newSqData == NULL){perror("Realloc Fail");return;}//赋予新空间地址sq->data = ptr_newSqData;//空间大小记录翻倍sq->capacity *= 2;}//数据后移直至腾出 pos 位置的空间for (int i = sq->size; i > pos; i--){sq->data[i] = sq->data[i - 1];}//写入数据*(sq->data + pos) = data;//数据长度+1sq->size++;
}
至于头插尾插数据,只不过是上述函数 pos 位置的区别。因此:
//pos = 0 便是头插
void DataPushHead(SeqTab* sq, DATATYPE data)
{DataInsert(sq, 0, data);
}
//pos = 数据尺寸便是尾插
void DataPushTail(SeqTab* sq, DATATYPE data)
{DataInsert(sq, sq->size, data);
}
在 main 函数里写入下列代码验证一下:
DataInsert(&sqList, 10, 32); //报错DataPushTail(&sqList, 10);DataPrint(&sqList); //打印 10DataPushHead(&sqList, 20);DataPrint(&sqList); //打印 20 10DataPushHead(&sqList, 3);DataPushTail(&sqList, 6);DataPushHead(&sqList, 8);DataPushHead(&sqList, 7);DataPushHead(&sqList, 2);DataPushTail(&sqList, 100);DataPushTail(&sqList, 432);DataPrint(&sqList); //打印 2 7 8 3 20 10 6 10 432

结果与预期无误。至此插入功能便已完成。
3.2、删
正如插入数据分为头插、尾插及指定插,删除也分头删及任意位删。与插入相反,删除数据需要在数据删除结束后关注数据长度与开辟的数据空间,当空间分配过大时,对多余空间进行回收。
同样先将以下三个函数声明添加到 seqTab.h 中:
//指定位置删除数据
extern void DataRemove(SeqTab*, int);
//删除头部数据
extern void DataPopHead(SeqTab*);
//删除尾部数据
extern void DataPopTail(SeqTab*);
DataRemove 函数流程图如下:

根据图中逻辑在 sqFunction.c 中写入以下:
void DataRemove(SeqTab* sq, int pos)
{//数据有效性判断assert(sq);if (pos < 0 || pos > sq->size - 1){printf("Illegal Position : %d\n", pos);return;}//列表不为空则执行if (sq->size - 1 >= 0){//由 pos 位开始,之后所有数据前移 1 位for (int i = pos; i < sq->size - 1; i++){sq->data[i] = sq->data[i + 1];}//数据长度-1sq->size--;}//开辟空间过大则执行if (sq->size < sq->capacity / 2){//申请新空间DATATYPE* ptr_newSqData = (DATATYPE*)realloc(sq->data, sizeof(DATATYPE) * (sq->capacity / 2));//空间申请结果判断if (ptr_newSqData == NULL){perror("Realloc Fail");return;}//赋予新空间地址sq->data = ptr_newSqData;//空间大小记录减半sq->capacity /= 2;}
}
至于头删尾删数据,也同样是上述函数 pos 位置的区别:
//头删 pos = 0
void DataPopHead(SeqTab* sq)
{DataRemove(sq, 0);
}
//尾删 pos = 数据长度-1
void DataPopTail(SeqTab* sq)
{DataRemove(sq, sq->size - 1);
}
之后同样是验证,将以下代码写到之前测试代码之后:
DataRemove(&sqList, 100); //报错DataRemove(&sqList, 3);DataPrint(&sqList); //打印 2 7 8 20 10 6 100 432DataPopHead(&sqList);DataPrint(&sqList); //打印 7 8 20 10 6 100 432DataPopTail(&sqList);DataPrint(&sqList); //打印 7 8 20 10 6 100DataPopTail(&sqList);DataPopTail(&sqList);DataPopTail(&sqList);DataPopTail(&sqList);DataPopTail(&sqList);DataPrint(&sqList); //打印 7DataPopTail(&sqList);DataPopTail(&sqList);DataPrint(&sqList); //因为 size = 0 ,pos = -1 , 报错
删除数据功能完毕。
3.3、改
改数据的功能实现起来,逻辑上毫无难度可言。以下函数声明添加到 seqTab.h 中:
//修改指定位置数据
extern void DataModify(SeqTab*, int, DATATYPE);
在 sqFunction.c 中写入:
void DataModify(SeqTab* sq, int pos, DATATYPE data)
{//数据有效性判断assert(sq);if (pos < 0 || pos > sq->size - 1){printf("Illegal Position : %d\n", pos);return;}//修改数据sq->data[pos] = data;
}
在 main 函数中追加以下代码验证:
for (int i = 0; i < 10; i++){DataPushTail(&sqList, i);}DataPrint(&sqList); //打印 0 1 2 3 4 5 6 7 8 9DataModify(&sqList, 100, 30); //报错DataModify(&sqList, 3, 30);DataPrint(&sqList); //打印 0 1 2 30 4 5 6 7 8 9

完毕。
3.4、查
查到数据返回该数据的位置,查不到返回 -1 。同样很简单。 seqTab.h 中写入声明:
//在表中查找数据
extern int DataSearch(SeqTab*, DATATYPE);
然后是 sqFunction.c 中写入:
int DataSearch(SeqTab* sq, DATATYPE data)
{//数据有效性判断assert(sq);//遍历数组for (int i = 0; i < sq->size; i++){//如果找到数据则返回下标if (sq->data[i] == data){return i;}}//遍历完毕仍找不到数据返回 -1return -1;
}
main 函数中验证:
int num = 1200;int pos = DataSearch(&sqList, num);if (pos == -1){printf("The number \"%d\" is not exist!\n", num);}else{printf("The position of number \"%d\" is %d\n", num, pos);}//打印不存在num = 9;pos = DataSearch(&sqList, num);if (pos == -1){printf("The number \"%d\" is not exist!\n", num);}else{printf("The position of number \"%d\" is %d\n", num, pos);}//打印 9DataModify(&sqList, DataSearch(&sqList, 8), 11001);DataPrint(&sqList); //打印 0 1 2 30 4 5 6 7 11001 9

至此增删改查功能实现均已完毕。除此之外,还有排序、截断等其他一系列可以自定的操作。总之,操作顺序表就是操作数组,实现起来难度几乎为 0 。
相关文章:
初级数据结构(一)——顺序表
文中代码源文件已上传:数据结构源码 <-上一篇 NULL | 初级数据结构(二)——链表 下一篇-> 1、顺序表的特点 1.1、数组 现实中数据记录一般都记录在表格中,如进货单、菜单等,它们的最大特点就是…...
实现:切换页面切换标题,扩展 vue-router 的类型
布局容器-页面标题 网址:https://router.vuejs.org/zh/guide/advanced/meta 给每一个路由添加 元信息 数据 router/index.ts const router createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{ path: /login, component: () > im…...
已通过考试和认证注册以及后续计划表
已通过考试和认证注册以及后续计划表 软考 - 计算机技术与软件专业技术资格(水平)考试信息系统集成及服务项目管理人员工程类考试计划你关注的证书样子 软考 - 计算机技术与软件专业技术资格(水平)考试 高级 信息系统项目管理师&…...
开源计算机视觉库OpenCV详解
目录 1、概述 2、OpenCV详细介绍 2.1、OpenCV的起源 2.2、OpenCV开发语言 2.3、OpenCV的应用领域 3、OpenCV模块划分 4、OpenCV源码文件结构 4.1、根目录介绍 4.2、常用模块介绍 4.3、CUDA加速模块 5、OpenCV配置以及Visual Studio使用OpenCV 6、关于Lena图片 7、…...
使用pytorch查看中间层特征矩阵以及卷积核参数
这篇是我对哔哩哔哩up主 霹雳吧啦Wz 的视频的文字版学习笔记 感谢他对知识的分享 1和4是之前讲过的alexnet和resnet模型 2是分析中间层特征矩阵的脚本 3是查看卷积核参数的脚本 1设置预处理方法 和图像训练的时候用的预处理方法保持一致 2实例化模型 3载入之前的模型参数 4载入…...
HarmonyOS4.0从零开始的开发教程09页签切换
HarmonyOS(七)页签切换 List组件和Grid组件的使用 Tabs组件的使用 概述 在我们常用的应用中,经常会有视图内容切换的场景,来展示更加丰富的内容。比如下面这个页面,点击底部的页签的选项,可以实现“首页…...
大电流H桥电机驱动电路的设计与解析(包括自举电路的讲解,以IR2104+LR7843为例)
大电流H桥电机驱动电路的设计与解析(包括自举电路的讲解,以IR2104LR7843为例) 电机驱动板主要采用两种驱动芯片,一种是全桥驱动(如:HIP4082),一种是半桥驱动(如ÿ…...
windows11 windows 11 (win11 win 11) 怎么安装 Python3 ? numpy? sounddevice? 声音信号处理库?
首先确认要安装的 sounddevice 库,链接:https://python-sounddevice.readthedocs.io/en/0.4.6/ 根据文档,可知最新的 sounddevice 版本是 0.4.6 进入安装页面查看,发现 Newest sounddevice 可以使用 pip 安装,如下图…...
git如何配置多个远程仓库,并且进行切换
一、配置多个远程仓库并进行切换,请按照以下步骤进行操作: 打开命令行终端,并进入您的 Git 仓库所在的目录。添加第一个远程仓库,使用以下命令:git remote add origin <第一个远程仓库的 URL>这里将远程仓库命名…...
计算机存储单位 + 程序编译过程
C语言的编译过程 计算机存储单位 头文件包含的两种方式 使用 C/C 程序常用的IDE 常用的C语言编译器: 在选择编译器时,需考虑平台兼容性、性能优化、调试工具和开发人员的个人偏好等因素。 详细教程可转 爱编程的大丙...
vue路由导航守卫(全局守卫、路由独享守卫、组件内守卫)
目录 一、什么是Vue路由导航守卫? 二、全局守卫 1、beforeEach 下面是一个beforeEach的示例代码: 2、beforeResolve 下面是一个beforeResolve的示例代码: 3、afterEach 下面是一个afterEach的示例代码: 三、路由独享守卫…...
单片机双机通信控制跑马灯
实验要求 两个单片机各驱动8个LED灯,构成两个跑马灯,要求甲单片机LED的点亮方式是从上至下,首先是最上面第一个点亮、其次是前两个点亮、其次是前三个点亮……直至8个灯全部点亮,8个灯全部灭,重复这个过程,…...
微信小程序:button微信开放能力打开客服会话分享到聊天框
文档 https://developers.weixin.qq.com/miniprogram/dev/component/button.html 打开客服会话 按钮关键属性 open-type"contact"功能按钮 <button class"mo-open-type"open-type"contact"> </button>分享 <button class&q…...
【数据结构】——队列实现二叉树的功能
前言:二叉树的实现方式多种多样,有数组实现满二叉树,有链表实现完全二叉树,今天我们就用队列来实现二叉树。 创建二叉树: typedef int BTDataType; typedef struct BinaryTreeNode {BTDataType data;struct BinaryTre…...
【已解决】Win7虚拟机安装VMtools报错
在做以前的实验的时候发现要用到Win7虚拟机,于是就安装了一个Win7的虚拟机,但是发现屏幕太小,而且来回复制文本、复制文件太不方便了,索性就安装了VMtools,发现还安装不成– 情况1 报错:本程序需要您将此…...
华为OD机试真题-小明找位置-2023年OD统一考试(C卷)
题目描述: 小朋友出操,按学号从小到大排成一列;小明来迟了,请你给小明出个主意,让他尽快找到他应该排的位置。 算法复杂度要求不高于nLog(n);学号为整数类型,队列规模<10000; 输…...
2023.2版idea安装教程,现在jdk8已经过去式了,不同idea支持的jdk不同。升级jdk后idea也要随之升级
下载idea2023.2版本,下载之前需要删除之前的版本,一定要删除干净,删除程序要勾选那两个delete 下载路径:其他版本 - IntelliJ IDEA (jetbrains.com.cn) 选择2023.2版本 下载后进入安装程序,选择安装目录,然…...
CSS3技巧36:让内容垂直居中的三种方式
让内容垂直居中,是一个很重要的应用情景,在很多场合都会需要。这也是面试的时候,一些考官喜欢拿来初面的小题目。 这里,小结下让内容垂直居中的三种方式。 当然,读者如果有更好的方法,也可以提出来。 基本…...
空间运算设备-Apple Vision Pro
苹果以其在科技领域的创新而闻名,他们致力于推动技术的边界,这在他们的产品中表现得非常明显。他们尝试开发一项的新型突破性显示技术。在 2023 年 6 月 5 日官网宣布将发布 Apple Vision Pro 头戴空间设备,我们一起来了解一下 Apple Vision …...
cocos creator “TypeError: Cannot set property ‘string‘ of null
背景: 学习cocos creator时遇到"TypeError: Cannot set property string of null" 错误。具体代码如下:property({ type: Label })public stepsLabel: Label | null null;update(deltaTime: number) {this.stepsLabel.string Math.floor(…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...
