当前位置: 首页 > news >正文

【数据结构】手撕顺序表

一,概念及结构

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储;

在数组上完成数据的增删查改。

 1, 静态顺序表:使用定长数组存储元素。

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

 

二,接口实现

静态顺序表只适用于确定知道需要存多少数据的场景;

静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用;

所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小,所以下面我们实现动态顺序表;

        1,顺序表的创建(动态)

//动态顺序表
typedef int SLDataType;typedef struct SqList
{SLDataType* a;int size;		//存储有效数据个数int capacity;	//容量空间大小
}SL;

这里我们将数据类型暂时定为int类型,typedefSLDataType,便于我们后续对顺序表数据类型的修改;

定义属性表为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大小的空间,这个自己可以任意修改,然后对sizecapacity进行赋值;

        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--;
}

如有不足之处欢迎来补充交流!

完结。。。


相关文章:

【数据结构】手撕顺序表

一&#xff0c;概念及结构 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构&#xff0c;一般情况下采用数组存储&#xff1b; 在数组上完成数据的增删查改。 1&#xff0c; 静态顺序表&#xff1a;使用定长数组存储元素。 2.&#xff0c;动态顺序表&#xff1…...

景联文科技数据标注:人体关键点标注用途及各点的位置定义

人体关键点标注是一种计算机视觉任务&#xff0c;指通过人工的方式&#xff0c;在指定位置标注上关键点&#xff0c;例如人脸特征点、人体骨骼连接点等&#xff0c;常用来训练面部识别模型以及统计模型。这些关键点可以表示图像的各个方面&#xff0c;例如角、边或特定特征。在…...

typescript基础之never

TypeScript 的 never 类型是一种特殊的类型&#xff0c;它表示的是那些永远不存在的值的类型。例如&#xff0c;一个抛出异常或无限循环的函数的返回值类型就是 never&#xff0c;因为它们永远不会返回任何值。never 类型是所有类型的子类型&#xff0c;也就是说&#xff0c;任…...

电子电路学习笔记之NCP304LSQ37T1G ——超低电流电压检测器

超低电流电压检测器是一种专门用于检测极小电流值的设备。它们常用于电子元件或电路中&#xff0c;用于监测电流的存在和程度。这些检测器通常具有高灵敏度和高精度&#xff0c;能够测量微安级别或更小的电流。 超低电流电压检测器的应用领域广泛&#xff0c;例如电池管理系统…...

【计算机组成原理】一文快速入门,很适合JAVA后端看

作者简介&#xff1a; CSDN内容合伙人、CSDN新星计划导师、JAVA领域优质创作者、阿里云专家博主&#xff0c;计算机科班出身、多年IT从业经验、精通计算机核心理论、Java SE、Java EE、数据库、中间件、分布式技术&#xff0c;参加过国产中间件的核心研发&#xff0c;对后端有…...

10万字智慧政务大数据平台项目建设方案222页[Word]

导读:原文《10万字智慧政务大数据平台项目建设方案222页[Word]》(获取来源见文尾),本文精选其中精华及架构部分,逻辑清晰、内容完整,为快速形成售前方案提供参考。 1.1 项目建设目标 推进市一级政府搭建数字政府建设的规划要求,结合市一级政府“互联网+政务服务”建设…...

Python-主线程控制子线程-4

需求&#xff1a;在Python-主线程控制子线程-3的基础上&#xff0c;新增使用UDP接收指令功能&#xff0c;代替从键盘输入指令 # 修改后的程序&#xff0c;主线程可以获取子线程的结果 import threading import time import queue import tracebackfrom loguru import logger i…...

设计模式二十二:策略模式(Strategy Pattern)

定义一系列算法&#xff0c;将每个算法封装成独立的对象&#xff0c;并使这些对象可互相替换。这使得在运行时可以动态地选择算法&#xff0c;而不必改变使用算法的客户端代码。策略模式的主要目标是将算法的定义与使用分离&#xff0c;使得客户端可以根据需要灵活地选择和切换…...

【c语言】结构体内存对齐,位段,枚举,联合

之前学完结构体&#xff0c;有没有对结构体的大小会很疑惑呢&#xff1f;&#xff1f;其实结构体在内存中存储时会存在内存对齐&#xff0c;捎带讲讲位段&#xff0c;枚举&#xff0c;和联合&#xff0c;跟着小张一起学习吧 结构体内存对齐 结构体的对齐规则: 第一个成员在与结…...

干货丨软件测试行业迎来新时代,AI将成为主流技术?

随着科技日新月异的发展&#xff0c;人工智能正逐渐渗透到我们生活的各方各面&#xff0c;从智能语音助手到自动驾驶汽车、从智能家居到人脸识别技术&#xff0c;AI正以其卓越的智能和学习能力引领着新时代的发展方向。 在这个快速演进的时代中&#xff0c;软件测试领域也受到了…...

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&#xff09;字符串截取 6-2&#xff09;字符串内置方法 7、元组、列表&#xff0c;及其遍历方式 7-1&#xff09;列表常用内…...

kafka架构和原理详解

Apache Kafka 是一个分布式流数据平台,用于高吞吐量、持久性、可扩展的发布和订阅消息。它具有高度的可靠性,被广泛用于构建实时数据流处理、日志收集和数据管道等应用。 基本架构 1. 主题(Topic): 主题是消息的逻辑分类生产者将消息发布到特定的主题中,而消费者可以订阅…...

wsl Ubuntu中非root的普通用户怎么直接执行docker命令

docker需要root权限&#xff0c;如果希望非root用户直接使用docker命令&#xff0c;而不是使用sudo&#xff0c;可以选择将该用户加入到docker用户组。 sudo groupadd docker&#xff1a;添加到groupadd用户组&#xff08;已经有docker用户组&#xff0c;所以可以不用再新增do…...

Web开发模式、API接口、restful规范、序列化和反序列化、drf安装和快速使用、路由转换器(复习)

一 Web开发模式 1. 前后端混合开发模式 前后端混合开发模式是一种开发方式&#xff0c;将前端和后端的开发工作结合在一起&#xff0c;以加快项目的开发速度和 提高协作效率。这种模式通常用于快速原型开发、小型项目或敏捷开发中。在前后端混合开发模式中&#xff0c;前端和…...

<AMBA总线篇> AXI总线协议介绍

目录 01 AXI协议简介 AXI协议特性 AXI协议传输特性 02 AXI协议架构 AXI协议架构 write transaction(写传输) read tramsaction(读传输) Interface and interconnect 典型的AXI系统拓扑 03 文章总结 大家好&#xff0c;这里是程序员杰克。一名平平无奇的嵌入式软件工程…...

一个简单的Python网络爬虫教程

网络爬虫是一种自动获取网页内容的程序&#xff0c;它可以从互联网上的网站中提取数据并进行分析。本教程将带您逐步了解如何使用 Python 构建一个简单的网络爬虫。 注意&#xff1a;在进行网络爬虫时&#xff0c;请遵守网站的使用条款和法律法规&#xff0c;避免对目标网站造…...

YARN资源管理框架论述

一、简介 为了实现一个Hadoop集群的集群共享、可伸缩性和可靠性&#xff0c;并消除早期MapReduce框架中的JobTracker性能瓶颈&#xff0c;开源社区引入了统一的资源管理框架YARN。 YARN是将JobTracker的两个主要功能&#xff08;资源管理和作业调度/监控&#xff09;分离&…...

Unity查找资源依赖关系

这个方法主要是发现资源乱用的情况&#xff0c;对应的逻辑可能要改一个才能用到自己的项目里面 [MenuItem("Tools/Prefab/查找选中资源依赖关系", false, 0)] public static void FindDependencies() { foreach (var guid in Selection.assetGUIDs…...

【操作系统】聊聊局部性原理是如何提升性能的

对于目前数据主导的系统&#xff0c;大多数都是Java/Go 技术栈MySQL&#xff0c;但是随着时间的推移&#xff0c;数据库数据的数据量过多&#xff0c;并且会频繁访问热点数据&#xff0c;为了提升系统的性能&#xff0c;一般都是加入缓存中间件、Redis。 局部性原理 我们知道…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

ffmpeg(四):滤镜命令

FFmpeg 的滤镜命令是用于音视频处理中的强大工具&#xff0c;可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下&#xff1a; ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜&#xff1a; ffmpeg…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...