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

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

二,接口实现
静态顺序表只适用于确定知道需要存多少数据的场景;
静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用;
所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小,所以下面我们实现动态顺序表;
1,顺序表的创建(动态)
//动态顺序表
typedef int SLDataType;typedef struct SqList
{SLDataType* a;int size; //存储有效数据个数int capacity; //容量空间大小
}SL;
这里我们将数据类型暂时定为int类型,typedef为SLDataType,便于我们后续对顺序表数据类型的修改;
定义属性表为SL*的指针a,有效数据个数size,现有容量capacity;
2,接口函数
// 顺序表初始化
void SLInit(SL* ps);
// 顺序表销毁
void SLDestroy(SL* ps);
// 检查空间,如果满了,进行增容
void SLChenkCapacity(SL* ps);
//顺序表尾插
void SLPushBack(SL* ps,SLDataType x);
//顺序表尾删
void SLPopBack(SL* ps);
//顺序表头插
void SLPushFront(SL* ps, SLDataType x);
//顺序表头删
void SLPopFront(SL* ps);
//顺序表打印
void SLPrint(SL* ps);
// 顺序表查找
int SeqListFind(SL* ps, SLDataType x);
// 顺序表在pos位置插入x
void SLInsert(SL*ps, int pos, SLDataType x);
// 顺序表在pos位置删除x
void SLErase(SL*ps, int pos);
3,初始化
//定义SL s1;//初始化SLInit(&s1);
// 顺序表初始化
void SLInit(SL* ps)
{assert(ps);ps->a = (SLDataType*)malloc(sizeof(SLDataType) * 4);if (ps->a== NULL){perror("malloc");exit(-1);}ps->size = 0;ps->capacity = 4;
}
首先要进行断言ps不能为空,如果ps为空则下面对ps解引用就会报错;
刚开始先给 a 申请4个SLDataType大小的空间,这个自己可以任意修改,然后对size和capacity进行赋值;
4,销毁
// 顺序表销毁
void SLDestroy(SL*ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->size = ps->capacity = 0;
}
然后就是销毁顺序表,直接用 free 释放掉 a 即可,再置为空指针,再重置 size 和 capacity ;
5,判断是否增容
// 检查空间,如果满了,进行增容
void SLChenkCapacity(SL* ps)
{assert(ps);if (ps->size == ps->capacity){ps->a = (SLDataType*)realloc(ps->a, ps->capacity * 2 * (sizeof(SLDataType)));if (ps->a == NULL){perror("realloc");exit(-1);}ps->capacity = ps->capacity * 2;}
}
像后面如果进行尾插,头插的话就需要检查空间是否需要增容了,也很好判断,当size等于capacity时就需要增容了,我们这里是选择直接扩容一倍;
然后再更新一下capacity的值就行了;
6,尾插
//顺序表尾插
void SLPushBack(SL* ps, SLDataType x)
{assert(ps);//检查空间SLChenkCapacity(ps);ps->a[ps->size] = x;ps->size++;
}
首先判断是否需要增容,此时size的值就是末尾的数的下标加一;
直接对其下标进行赋值,再让size加一;
7,尾删
//顺序表尾删
void SLPopBack(SL* ps)
{assert(ps);//温柔的检查//if (ps->size == 0)// return;//暴力检查assert(ps->size > 0);ps->size--;
}
这里有两种检查方式,推荐暴力检查法,要删除值,size的值必须大于0;
然后直接令size减一即可,访问不到即为删除;
8,头插
//顺序表头插
void SLPushFront(SL* ps, SLDataType x)
{assert(ps);SLChenkCapacity(ps);int end = ps->size-1;while (end >= 0){ps->a[end + 1] = ps->a[end];end--; }ps->a[0] = x;ps->size++;
}
还是先判断是否需要增容,然后先将整体的值往后推一位;
给头赋值,令size加一;
9,头删
//顺序表头删
void SLPopFront(SL* ps)
{assert(ps);assert(ps->size > 0);int i = 0;while (i < ps->size - 1){ps->a[i] = ps->a[i + 1];i++;}ps->size--;
}
要删除数据首先数据不能为空,要进行断言一下;
然后将整体往前推一位,再令size减一;
10,打印
//顺序表打印
void SLPrint(SL* ps)
{assert(ps);int i = 0;for (i = 0; i < ps->size; i++){printf("%d ", ps->a[i]);}printf("\n");
}
size是数据个数,其减一就是末尾数据的下标,然后进行遍历打印即可;
11,查找
// 顺序表查找
int SeqListFind(SL* ps, SLDataType x)
{assert(ps);int i = 0;for (i = 0; i < ps->size; i++){if (ps->a[i] == x)return i;}return -1;
}
直接遍历数组进行查找然后返回下标,没有则返回-1;
12,指定位置进行插入
// 顺序表在pos位置插入x
void SLInsert(SL*ps, int pos, SLDataType x)
{assert(ps);assert(pos>=0 && pos <= ps->size);SLChenkCapacity(ps);int end = ps->size - 1;while (end >=pos){ps->a[end + 1] = ps->a[end];end--;}ps->a[pos] = x;ps->size++;
}
首先判断pos要大于等于0且小于等于size,是否需要增容;
然后从pos数组的值往后推一位,再对其位置重新赋值,再令size++;
13,指定位置进行删除
// 顺序表在pos位置删除x
void SLErase(SL*ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);int i = pos;while (i < ps->size - 1){ps->a[i] = ps->a[i + 1];i++;}ps->size--;
}
首先还是要判断pos的值,大于等于0小于size,因为数组下标为size是没有值的,所以pos不能等于size;
然后在pos处往前推一位,令size--;
三,源码
1,头文件
SqList.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>//动态顺序表
typedef int SLDataType;typedef struct SqList
{SLDataType* a;int size; //存储有效数据个数int capacity; //容量空间大小
}SL;// 顺序表初始化
void SLInit(SL* ps);
// 顺序表销毁
void SLDestroy(SL* ps);
// 检查空间,如果满了,进行增容
void SLChenkCapacity(SL* ps);
//顺序表尾插
void SLPushBack(SL* ps,SLDataType x);
//顺序表尾删
void SLPopBack(SL* ps);
//顺序表头插
void SLPushFront(SL* ps, SLDataType x);
//顺序表头删
void SLPopFront(SL* ps);
//顺序表打印
void SLPrint(SL* ps);
// 顺序表查找
int SeqListFind(SL* ps, SLDataType x);
// 顺序表在pos位置插入x
void SLInsert(SL*ps, int pos, SLDataType x);
// 顺序表在pos位置删除x
void SLErase(SL*ps, int pos);
2,执行文件
SqList.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"SqList.h"// 顺序表初始化
void SLInit(SL* ps)
{assert(ps);ps->a = (SLDataType*)malloc(sizeof(SLDataType) * 4);if (ps->a== NULL){perror("malloc");exit(-1);}ps->size = 0;ps->capacity = 4;
}// 顺序表销毁
void SLDestroy(SL*ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->size = ps->capacity = 0;
}// 检查空间,如果满了,进行增容
void SLChenkCapacity(SL* ps)
{assert(ps);if (ps->size == ps->capacity){ps->a = (SLDataType*)realloc(ps->a, ps->capacity * 2 * (sizeof(SLDataType)));if (ps->a == NULL){perror("realloc");exit(-1);}ps->capacity = ps->capacity * 2;}
}//顺序表尾插
void SLPushBack(SL* ps, SLDataType x)
{assert(ps);//检查空间SLChenkCapacity(ps);ps->a[ps->size] = x;ps->size++;
}//顺序表尾删
void SLPopBack(SL* ps)
{assert(ps);//温柔的检查//if (ps->size == 0)// return;//暴力检查assert(ps->size > 0);ps->size--;
}//顺序表头插
void SLPushFront(SL* ps, SLDataType x)
{assert(ps);SLChenkCapacity(ps);int end = ps->size-1;while (end >= 0){ps->a[end + 1] = ps->a[end];end--; }ps->a[0] = x;ps->size++;
}//顺序表头删
void SLPopFront(SL* ps)
{assert(ps);assert(ps->size > 0);int i = 0;while (i < ps->size - 1){ps->a[i] = ps->a[i + 1];i++;}ps->size--;
}//顺序表打印
void SLPrint(SL* ps)
{assert(ps);int i = 0;for (i = 0; i < ps->size; i++){printf("%d ", ps->a[i]);}printf("\n");
}// 顺序表查找
int SeqListFind(SL* ps, SLDataType x)
{assert(ps);int i = 0;for (i = 0; i < ps->size; i++){if (ps->a[i] == x)return i;}return -1;
}// 顺序表在pos位置插入x
void SLInsert(SL*ps, int pos, SLDataType x)
{assert(ps);assert(pos>=0 && pos <= ps->size);SLChenkCapacity(ps);int end = ps->size - 1;while (end >=pos){ps->a[end + 1] = ps->a[end];end--;}ps->a[pos] = x;ps->size++;
}// 顺序表在pos位置删除x
void SLErase(SL*ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);int i = pos;while (i < ps->size - 1){ps->a[i] = ps->a[i + 1];i++;}ps->size--;
}
如有不足之处欢迎来补充交流!
完结。。。
相关文章:
【数据结构】手撕顺序表
一,概念及结构 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储; 在数组上完成数据的增删查改。 1, 静态顺序表:使用定长数组存储元素。 2.,动态顺序表࿱…...
景联文科技数据标注:人体关键点标注用途及各点的位置定义
人体关键点标注是一种计算机视觉任务,指通过人工的方式,在指定位置标注上关键点,例如人脸特征点、人体骨骼连接点等,常用来训练面部识别模型以及统计模型。这些关键点可以表示图像的各个方面,例如角、边或特定特征。在…...
typescript基础之never
TypeScript 的 never 类型是一种特殊的类型,它表示的是那些永远不存在的值的类型。例如,一个抛出异常或无限循环的函数的返回值类型就是 never,因为它们永远不会返回任何值。never 类型是所有类型的子类型,也就是说,任…...
电子电路学习笔记之NCP304LSQ37T1G ——超低电流电压检测器
超低电流电压检测器是一种专门用于检测极小电流值的设备。它们常用于电子元件或电路中,用于监测电流的存在和程度。这些检测器通常具有高灵敏度和高精度,能够测量微安级别或更小的电流。 超低电流电压检测器的应用领域广泛,例如电池管理系统…...
【计算机组成原理】一文快速入门,很适合JAVA后端看
作者简介: CSDN内容合伙人、CSDN新星计划导师、JAVA领域优质创作者、阿里云专家博主,计算机科班出身、多年IT从业经验、精通计算机核心理论、Java SE、Java EE、数据库、中间件、分布式技术,参加过国产中间件的核心研发,对后端有…...
10万字智慧政务大数据平台项目建设方案222页[Word]
导读:原文《10万字智慧政务大数据平台项目建设方案222页[Word]》(获取来源见文尾),本文精选其中精华及架构部分,逻辑清晰、内容完整,为快速形成售前方案提供参考。 1.1 项目建设目标 推进市一级政府搭建数字政府建设的规划要求,结合市一级政府“互联网+政务服务”建设…...
Python-主线程控制子线程-4
需求:在Python-主线程控制子线程-3的基础上,新增使用UDP接收指令功能,代替从键盘输入指令 # 修改后的程序,主线程可以获取子线程的结果 import threading import time import queue import tracebackfrom loguru import logger i…...
设计模式二十二:策略模式(Strategy Pattern)
定义一系列算法,将每个算法封装成独立的对象,并使这些对象可互相替换。这使得在运行时可以动态地选择算法,而不必改变使用算法的客户端代码。策略模式的主要目标是将算法的定义与使用分离,使得客户端可以根据需要灵活地选择和切换…...
【c语言】结构体内存对齐,位段,枚举,联合
之前学完结构体,有没有对结构体的大小会很疑惑呢??其实结构体在内存中存储时会存在内存对齐,捎带讲讲位段,枚举,和联合,跟着小张一起学习吧 结构体内存对齐 结构体的对齐规则: 第一个成员在与结…...
干货丨软件测试行业迎来新时代,AI将成为主流技术?
随着科技日新月异的发展,人工智能正逐渐渗透到我们生活的各方各面,从智能语音助手到自动驾驶汽车、从智能家居到人脸识别技术,AI正以其卓越的智能和学习能力引领着新时代的发展方向。 在这个快速演进的时代中,软件测试领域也受到了…...
MacOS goland go1.21 debug问题
安装dlv brew install dlv 安装之后在终端会显示所在目录 类似/usr/local/Cellar/delve/1.21.0/bin 配置goland 在文件系统中找到goland 右击选择show package contents -> Contents -> plugins -> go 尝试替换 其中对应系统 的 dlv 结果还是不行 然后打开应用gol…...
python 笔记(1)——基础和常用部分
目录 1、print 输出不换行 2、格式化输出字符串 3、浮点数的处理 4、进制转换和ASCII与字符间的转换 5、随机数 6、字符串截取和内置方法 6-1)字符串截取 6-2)字符串内置方法 7、元组、列表,及其遍历方式 7-1)列表常用内…...
kafka架构和原理详解
Apache Kafka 是一个分布式流数据平台,用于高吞吐量、持久性、可扩展的发布和订阅消息。它具有高度的可靠性,被广泛用于构建实时数据流处理、日志收集和数据管道等应用。 基本架构 1. 主题(Topic): 主题是消息的逻辑分类生产者将消息发布到特定的主题中,而消费者可以订阅…...
wsl Ubuntu中非root的普通用户怎么直接执行docker命令
docker需要root权限,如果希望非root用户直接使用docker命令,而不是使用sudo,可以选择将该用户加入到docker用户组。 sudo groupadd docker:添加到groupadd用户组(已经有docker用户组,所以可以不用再新增do…...
Web开发模式、API接口、restful规范、序列化和反序列化、drf安装和快速使用、路由转换器(复习)
一 Web开发模式 1. 前后端混合开发模式 前后端混合开发模式是一种开发方式,将前端和后端的开发工作结合在一起,以加快项目的开发速度和 提高协作效率。这种模式通常用于快速原型开发、小型项目或敏捷开发中。在前后端混合开发模式中,前端和…...
<AMBA总线篇> AXI总线协议介绍
目录 01 AXI协议简介 AXI协议特性 AXI协议传输特性 02 AXI协议架构 AXI协议架构 write transaction(写传输) read tramsaction(读传输) Interface and interconnect 典型的AXI系统拓扑 03 文章总结 大家好,这里是程序员杰克。一名平平无奇的嵌入式软件工程…...
一个简单的Python网络爬虫教程
网络爬虫是一种自动获取网页内容的程序,它可以从互联网上的网站中提取数据并进行分析。本教程将带您逐步了解如何使用 Python 构建一个简单的网络爬虫。 注意:在进行网络爬虫时,请遵守网站的使用条款和法律法规,避免对目标网站造…...
YARN资源管理框架论述
一、简介 为了实现一个Hadoop集群的集群共享、可伸缩性和可靠性,并消除早期MapReduce框架中的JobTracker性能瓶颈,开源社区引入了统一的资源管理框架YARN。 YARN是将JobTracker的两个主要功能(资源管理和作业调度/监控)分离&…...
Unity查找资源依赖关系
这个方法主要是发现资源乱用的情况,对应的逻辑可能要改一个才能用到自己的项目里面 [MenuItem("Tools/Prefab/查找选中资源依赖关系", false, 0)] public static void FindDependencies() { foreach (var guid in Selection.assetGUIDs…...
【操作系统】聊聊局部性原理是如何提升性能的
对于目前数据主导的系统,大多数都是Java/Go 技术栈MySQL,但是随着时间的推移,数据库数据的数据量过多,并且会频繁访问热点数据,为了提升系统的性能,一般都是加入缓存中间件、Redis。 局部性原理 我们知道…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
9-Oracle 23 ai Vector Search 特性 知识准备
很多小伙伴是不是参加了 免费认证课程(限时至2025/5/15) Oracle AI Vector Search 1Z0-184-25考试,都顺利拿到certified了没。 各行各业的AI 大模型的到来,传统的数据库中的SQL还能不能打,结构化和非结构的话数据如何和…...
Python实现简单音频数据压缩与解压算法
Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中,压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言,提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...
TCP/IP 网络编程 | 服务端 客户端的封装
设计模式 文章目录 设计模式一、socket.h 接口(interface)二、socket.cpp 实现(implementation)三、server.cpp 使用封装(main 函数)四、client.cpp 使用封装(main 函数)五、退出方法…...
ArcPy扩展模块的使用(3)
管理工程项目 arcpy.mp模块允许用户管理布局、地图、报表、文件夹连接、视图等工程项目。例如,可以更新、修复或替换图层数据源,修改图层的符号系统,甚至自动在线执行共享要托管在组织中的工程项。 以下代码展示了如何更新图层的数据源&…...
高保真组件库:开关
一:制作关状态 拖入一个矩形作为关闭的底色:44 x 22,填充灰色CCCCCC,圆角23,边框宽度0,文本为”关“,右对齐,边距2,2,6,2,文本颜色白色FFFFFF。 拖拽一个椭圆,尺寸18 x 18,边框为0。3. 全选转为动态面板状态1命名为”关“。 二:制作开状态 复制关状态并命名为”开…...
