数据结构:顺序表详解
数据结构:顺序表详解
- 一、 线性表
- 二、 顺序表概念及结构
- 1. 静态顺序表:使用定长数组存储元素。
- 2. 动态顺序表:使用动态开辟的数组存储。
- 三、接口实现
- 1. 创建
- 2. 初始化
- 3. 扩容
- 4. 打印
- 5. 销毁
- 6. 尾插
- 7. 尾删
- 8. 头插
- 9. 头删
- 10. 插入任意位置数据
- 11. 删除任意位置数据
- 12. 查找
- 13. 修改
- 四:所有代码

一、 线性表
线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串…
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的。
线性表在物理上存储时,通常以数组和链式结构的形式.

二、 顺序表概念及结构
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。
顺序表一般可以分为:
1. 静态顺序表:使用定长数组存储元素。

2. 动态顺序表:使用动态开辟的数组存储。

三、接口实现
静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小,所以下面我们实现动态顺序表。
基本增删查改接口
//对数据管理 --- 增删查改
void SLInit(SL* ps); //初始化
void SLDestory(SL* ps); //释放
void SLPrint(SL* ps); //打印
void SLCheakCapacity(SL* ps); //检查容量 -- 扩容//头插头删 尾插尾删
void SLPushBack(SL* ps, SLDateType x); //尾插
void SLPopBack(SL* ps); //尾删
void SLPushFront(SL* ps, SLDateType x);//头插
void SLPopFront(SL* ps); //头删//返回下标,没找到返回-1
int SLFind(SL* ps, SLDateType); //查找元素,返回下标//在pos位置插入x
void SLInsert(SL* ps, int pos, SLDateType x); //任意位置插入
//在pos位置删除x
void SLErase(SL* ps, int pos); //任意位置删除void SLModify(SL* ps, int pos, SLDateType x);//修改
1. 创建
由于在实际工程中,项目的实现都是采用模块化进行实现的。所以在此处博主也采用了模块化的方式进行实现。

#pragma once#include <stdio.h>
#include <assert.h>
#include <stdlib.h>//动态顺序表
typedef int SLDateType;
typedef struct SeqList
{SLDateType* a;//指向动态开辟的数组int size; //有效数据的个数int capacity;//容量空间的大小
}SL;
为了后续好修改类型数据,在此采用typedef将结构体类型struct SeqList 重新命名为SL。
在实际开发过程中,为了开发人员更好的输入数据,一般我们会将输入数据的数据类型重命名为SLDateType。(在本篇博客中,采用typedef将其数据类型int重命名为SLDateType)
2. 初始化
初始化时,理论上我们只需要开辟一个空间并置为空指针,并将结构体中的数据全部初始化为0即可。
但在实际开发过程中,我们一般会开辟一定大小的空间(本篇博客开4个空间,但具体开多少,各位可自行选择)。
代码实现:
void SLInit(SL* ps)
{assert(ps);ps->a = (SLDateType*)malloc(4 * sizeof(SLDateType));//开辟4个空间if (ps->a == NULL){perror("malloc");exit(-1);}//开辟成功ps->capacity = 4;//开辟多少空间,容量变为多少ps->size = 0;
}
3. 扩容
在后续我们插入数据时,已开辟容量可能已经无法满足需求了。这是就需要扩容。
那一次扩到多少呢?
在实际开发过程中我们一般是扩到原有空间的两倍。(当然你也可以开1000倍,只要后台空间足够大)
代码实现:
void SLCheakCapacity(SL* ps)
{assert(ps);if (ps->size == ps->capacity){//开辟空间X2SLDateType* tmp = (SLDateType*)realloc(ps->a, ps->capacity * sizeof(SLDateType) * 2);if (tmp == NULL){perror("realloc");exit(-1);}//开辟成功ps->a = tmp;ps->capacity *= 2;}
}
4. 打印
上述函数定义完成后,我们通常需要测试打印以下相关数据,来判断相关函数定义是否成功.
代码实现:
void SLPrint(SL* ps)
{assert(ps);for (int i = 0; i < ps->size; i++){printf("%d ", ps->a[i]);}printf("\n");
}
5. 销毁
由于上述空间是动态开辟的。所以当我们使用完时,要及时销毁,释放空间。
代码实现:
void SLDestory(SL* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->capacity = ps->size = 0;
}
6. 尾插
尾插:在尾部插入一个数据。

但是在数据的尾部插入一个数据时,我们需要考虑一个问题:原有空间是否可以容纳新的数据,是否需要扩容。
所以我们在插入数据时,要先调用 SLCheakCapacity函数来检查是否需要扩容。
代码实现:
void SLPushBack(SL* ps, SLDateType x)
{assert(ps);SLCheakCapacity(ps);//检查是否需要扩容ps->a[ps->size] = x;ps->size++;
}
7. 尾删
尾删:删除尾部最后的一个元素。

但尾删同样也要考虑一个问题,空间中是否还有数据给我们删除。
所以在进行尾删时,我们可以采用assert函数断言空间中还有数据。
代码实现:
void SLPopBack(SL* ps)
{assert(ps);assert(ps->size >= 0);//断言空间中还有元素ps->size--;//下标减1
}
在删除数据时,我们不用将原有数据删除。只需要下标减1即可。
原因在于我们时根据下标来使用数据的,当下标减1后,尾部最后一个数据便无法进行访问。
Tips:
- 越界是不一定报错的,系统对越界的检查是一种设岗抽查。
- 以VS2022为例,微软公司在数据的开始前和结尾后的一小段空间设有一些特殊值。当程序结束或内存空间释放时,编译器就会检查这些值是否发生改变, 从而触发程序的保护机制。但如果这些值没有发生改变,即使发生越界访问,程序也不会报错。就像如果你酒驾,交警只在二环设关卡,但只要你不去二环,你就没事不会被发现。(每个编译器略有差异)
8. 头插
头插:在数据最开始地方插入数据。

同样,头插也要调用 SLCheakCapacity函数来检查空间是否足够,是否需要扩容。
代码实现:
void SLPushFront(SL* ps, SLDateType x)
{assert(ps);SLCheakCapacity(ps);//检查是否需要扩容//移动数据int i = ps->size-1;while (i >= 0){ps->a[i + 1] = ps->a[i];i--;}//移动数据完成,插入元素。同时有效个数加1ps->a[0] = x;ps->size++;
}
9. 头删
头删:删除数据最开始的元素。

思路和头插类似,只要下标从1开始,所有数据依次向前移动1位,再把有限个数减1即可。
同时头删也需要使用assert函数断言原有空间中还有数据可以删除。
代码实现:
void SLPopFront(SL* ps)
{assert(ps);assert(ps->size >= 0);//空间中还有数据可以删除//移动数据for (int begin = 1; begin < ps->size; begin++){ps->a[begin - 1] = ps->a[begin];}ps->size--;//有效个数减1
}
10. 插入任意位置数据
由于顺序表要求数据是连续存放的,所以我们只需要找到输入位置的下标pos即可。
【代码思路】:首先我们要检查输入下标是否合法,是有效下标;并检查是否有足够空间来容纳新数据,是否需要扩容。之后从输入的数据下标开始,所有元素向后移动一位,并把新数据插入到下标为pos处即可。
代码实现:
void SLInsert(SL* ps, int pos, SLDateType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);//检查下标是否合法SLCheakCapacity(ps); //检查空间是否足够//移动数据int end = ps->size - 1;while (end >= pos){ps->a[end + 1] = ps->a[end];end--;}ps->a[pos] = x;ps->size++;
}
11. 删除任意位置数据
【代码思路】:和插入任何位置数据思想类似。首先我们要检查输入下标pos是否合法。之后从输入下标开始,后一个元素拷贝到前一个元素空间。
代码实现:
void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);//下标是否合法//移动数据int begin = pos+1;while (begin < ps->size){ps->a[begin - 1] = ps->a[begin];begin++;}ps->size--;
}
12. 查找
【代码思路】:要查找某个元素。由于这里只是最简单的查找,我们直接暴力查找,遍历整个数组返回下标即可。更为复杂的数据查找,会有更高阶的数据结构来实现。
代码实现:
int SLFind(SL* ps, SLDateType x)
{assert(ps);for (int i = 0; i < ps->size; i++){if (x == ps->a[i])return i;}return -1;
}
13. 修改
【代码思路】: 要实现修改数据,我们只需要先判断输入下标是否合法。在将对应下标数据进行修改即可。
代码实现:
void SLModify(SL* ps, int pos, SLDateType x)
{assert(ps);assert(pos >= 0 && pos < ps->size);ps->a[pos] = x;
}
四:所有代码
SeqList.h源文件
#include <assert.h>
#include <stdlib.h>//动态顺序表
typedef int SLDateType;
typedef struct SeqList
{SLDateType* a;int size;int capacity;
}SL;//对数据管理 --- 增删查改
void SLInit(SL* ps);
void SLDestory(SL* ps);
void SLPrint(SL* ps);
void SLCheakCapacity(SL* ps);//头插头删 尾插尾删
void SLPushBack(SL* ps, SLDateType x);
void SLPopBack(SL* ps);
void SLPushFront(SL* ps, SLDateType x);
void SLPopFront(SL* ps);//返回下标,没找到返回-1
int SLFind(SL* ps, SLDateType);//在pos位置插入x
void SLInsert(SL* ps, int pos, SLDateType x);
//在pos位置删除x
void SLErase(SL* ps, int pos);void SLModify(SL* ps, int pos, SLDateType x);
SeqList.c头文件
#define _CRT_SECURE_NO_WARNINGS#include "SeqList.h"void SLInit(SL* ps)
{assert(ps);ps->a = (SLDateType*)malloc(4 * sizeof(SLDateType));if (ps->a == NULL){perror("malloc");exit(-1);}//开辟成功ps->capacity = 4;ps->size = 0;
}void SLDestory(SL* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->capacity = ps->size = 0;
}void SLPrint(SL* ps)
{assert(ps);for (int i = 0; i < ps->size; i++){printf("%d ", ps->a[i]);}printf("\n");
}void SLCheakCapacity(SL* ps)
{assert(ps);if (ps->size == ps->capacity){SLDateType* tmp = (SLDateType*)realloc(ps->a, ps->capacity * sizeof(SLDateType) * 2);if (tmp == NULL){perror("realloc");exit(-1);}ps->a = tmp;ps->capacity *= 2;}
}void SLPushBack(SL* ps, SLDateType x)
{assert(ps);/*SLCheakCapacity(ps);ps->a[ps->size] = x;ps->size++;*/SLInsert(ps, ps->size, x);
}void SLPopBack(SL* ps)
{assert(ps);assert(ps->size >= 0);/*ps->size--;*/SLErase(ps, 0);
}void SLPushFront(SL* ps, SLDateType x)
{assert(ps);SLCheakCapacity(ps);//移动数据/*int i = ps->size-1;while (i >= 0){ps->a[i + 1] = ps->a[i];i--;}ps->a[0] = x;ps->size++;*/SLInsert(ps, 0, x);
}void SLPopFront(SL* ps)
{assert(ps);assert(ps->size >= 0);/*for (int begin = 1; begin < ps->size; begin++){ps->a[begin - 1] = ps->a[begin];}ps->size--;*/SLErase(ps, 0);
}int SLFind(SL* ps, SLDateType x)
{assert(ps);for (int i = 0; i < ps->size; i++){if (x == ps->a[i])return i;}return -1;
}void SLInsert(SL* ps, int pos, SLDateType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);SLCheakCapacity(ps);int end = ps->size - 1;while (end >= pos){ps->a[end + 1] = ps->a[end];end--;}ps->a[pos] = x;ps->size++;}void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);int begin = pos+1;while (begin < ps->size){ps->a[begin - 1] = ps->a[begin];begin++;}ps->size--;
}void SLModify(SL* ps, int pos, SLDateType x)
{assert(ps);assert(pos >= 0 && pos < ps->size);ps->a[pos] = x;
}


相关文章:
数据结构:顺序表详解
数据结构:顺序表详解 一、 线性表二、 顺序表概念及结构1. 静态顺序表:使用定长数组存储元素。2. 动态顺序表:使用动态开辟的数组存储。三、接口实现1. 创建2. 初始化3. 扩容4. 打印5. 销毁6. 尾插7. 尾删8. 头插9. 头删10. 插入任意位置数据…...
采集数据筛选-过滤不要数据或只保留指定数据
采集文章数据,有时候会遇到一些不需要采集的数据,或者只想采集一些特定的数据,可以使用简数采集器的内容过滤功能,对采集的数据进行筛选,只有符合的数据才采集保留。 可以用于过滤掉一些广告、专题、网站首页等无效数…...
RISC-V基础指令之shift移动指令slli、srli、srai、sll、srl、sra
RISC-V的shift指令是用于对一个寄存器或一个立即数进行位移运算,并将结果存放在另一个寄存器中的指令。位移运算就是把一个操作数的每一位向左或向右移动一定的位数,得到一个新的位。RISC-V的shift指令有以下几种: slli:左逻辑位…...
【沁恒蓝牙mesh】CH58x flash分区与数据存储管理
本文主要介绍了 沁恒蓝牙芯片 CH58x 的flash 分区与数据存储管理 📋 个人简介 💖 作者简介:大家好,我是喜欢记录零碎知识点的小菜鸟。😎📝 个人主页:欢迎访问我的 Ethernet_Comm 博客主页&…...
Ctfshow web入门 JWT篇 web345-web350 详细题解 全
CTFshow JWT web345 先看题目,提示admin。 抓个包看看看。 好吧我不装了,其实我知道是JWT。直接开做。 在jwt.io转换后,发现不存在第三部分的签证,也就不需要知道密钥。 全称是JSON Web Token。 通俗地说,JWT的本质…...
2023年国家留学基金委(CSC)青年骨干教师项目即将开始申报
国家留学基金委(以下简称CSC)的青年骨干教师出国研修项目(即高校合作项目),将于2023年9月10-25日进行网上报名及申请受理。知识人网小编特提醒申请者注意流程及政策,以防错过申报时间。 青年骨干教师项目&a…...
GC垃圾回收器【入门笔记】
GC:Garbage Collectors 垃圾回收器 C/C,手动回收内存;难调试、门槛高。忘记回收、多次回收等问题 Java、Golang等,有垃圾回收器:自动回收,技术门槛降低 一、如何定位垃圾? https://www.infoq.c…...
在 React 中渲染大型数据集的 3 种方法
随着 Web 应用程序变得越来越复杂,我们需要找到有效的方法来优化性能和渲染大型数据集。在 React 应用程序中处理大型数据集时,一次呈现所有数据可能会导致性能不佳和加载时间变慢。 虚拟化是一种通过一次仅呈现数据集的一部分来解决此问题的技术&#…...
uniapp iOS 消息推送扩展:后台/杀死app进程状态能语音播报
文章目录 引言I 前期准备1.1 配置扩展1.2 测试报文II iOS Extension(扩展)2.1 插件作者配置2.2 插件使用者配置see also引言 HBuilderX3.1.5+版本uni原生插件支持iOS Extension(扩展)。 消息推送离线语音播报插件获取方式: 公z号:iOS逆向: 离线包x10, 源码是x15。 实…...
批量创建可配置物料参数文件
启用可配置物料之后,每次创建新的物料需要通过CU41创建可配置物料,没找大批量创建的程序,所以SHDB录屏搞了一个代码。 前提:物料主数据初始化通过程序导入时,可配置物料参数文件已按照物料代码赋值。 效果…...
性能压力测试的重要性与实施方法
性能压力测试是在软件开发过程中评估系统在不同负载条件下的表现和稳定性的关键步骤。这种测试是为了确定系统在正常和峰值负载下的性能表现,以验证系统是否能够满足用户需求,同时发现潜在的性能问题并加以解决。 首先,性能压力测试对于确保系…...
HCIP入门静态实验
题目及要求 第一步:拓扑的搭建 第二步:路由、IP的配置 r1: <Huawei>sys Enter system view, return user view with CtrlZ. [Huawei]sys r1 [r1]int loop [r1]int LoopBack 0 [r1-LoopBack0]ip add 192.168.1.65 27 [r1-LoopBack0]int loop 1 […...
Vue与js的融合,如何编写现代化的前端应用
随着Web应用的不断发展,前端开发已经成为了当今互联网行业中最为流行和重要的领域之一。而在前端开发中,JavaScript无疑是最为常用和基础的语言之一。而Vue.js作为一种轻量级的JavaScript框架,它的出现极大地简化了前端开发的过程,…...
Boost开发指南-3.10singleton_pool
singleton_pool singleton_pool与 pool的接口完全一致,可以分配简单数据类型(POD)的内存指针,但它是一个单件。 singleton_pool位于名字空间boost,为了使用singleton_pool组件,需要包含头文件<boost/p…...
腾讯云从业者认证考试考点——云网络产品
文章目录 腾讯云网络产品功能网络产品概述负载均衡(Cloud Load Balancer)私有网络(Virtual Private Cloud,VPC)专线接入弹性网卡(多网卡热插拔服务)NAT网关(NAT Gateway)…...
Miniled透明屏:超薄、轻便,还有哪些特点?
Miniled透明屏是一种新型的显示屏技术,它采用了微小的LED灯珠作为显示单元,通过透明的材料进行封装,使得整个屏幕具有透明的特性。Miniled透明屏具有以下几个特点: 首先,Miniled透明屏具有高亮度和高对比度的特点。 由…...
MySQL 极速安装使用与卸载
目录 mysql-5.6.51 极速安装使用与卸载 sqlyog工具 mysql简化 mysql-8.1.0下载配置 再完善 mysql-5.6.51 极速安装使用与卸载 mysql-8.1.0下载安装在后 mysql中国官网 MySQLhttps://www.mysql.com/cn/ 点击MySQL社区服务器 点击历史档案 下载完 解压 用管理员运行cmd&a…...
举个栗子!Tableau 技巧(256):灵活折叠文本表的多级数据行
通常,Tableau 默认的图表分层结构是统一打开或关上,有什么办法可以按需选择展开或折叠?如下示例:单击“”展开层级,单击“-“收起层级。 可以试试集操作!今天的栗子,就来分享具体实现方法吧~ 本…...
Android View 初始化完成后,如果再调用measure再设置点击事件则点击事件会失效的解决方案
比如LinearLayout 或RecyclerView 我们在初始化完成并加载完数据后再次调用measure计算高度再setLayoutParams 会导致后面设置的点击事件失效。 比如: RecyclerView rv_select dialog.findViewById(R.id.rv_select); //点击事件rv_select.setOnItemClickListener(n…...
客户端电脑使用 FTP的Cadence_CIS库方法说明 (下)
简介:随着企业的规模扩大,硬件工程师的增多,使用统一服务器上的库管理,可以减少设计错误,提高效率。 使用在FTP上布局Cadence_CIS库,是目前的主流的做法之一; 本文方法,用于已经配置…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing
Muffin 论文 现有方法 CRADLE 和 LEMON,依赖模型推理阶段输出进行差分测试,但在训练阶段是不可行的,因为训练阶段直到最后才有固定输出,中间过程是不断变化的。API 库覆盖低,因为各个 API 都是在各种具体场景下使用。…...
VisualXML全新升级 | 新增数据库编辑功能
VisualXML是一个功能强大的网络总线设计工具,专注于简化汽车电子系统中复杂的网络数据设计操作。它支持多种主流总线网络格式的数据编辑(如DBC、LDF、ARXML、HEX等),并能够基于Excel表格的方式生成和转换多种数据库文件。由此&…...
ubuntu22.04 安装docker 和docker-compose
首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...
