当前位置: 首页 > 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。 局部性原理 我们知道…...

linux之kylin系统nginx的安装

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

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

C# 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?

uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件&#xff0c;用于在原生应用中加载 HTML 页面&#xff1a; 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S &#xff08;client/server 客户端/服务器&#xff09;&#xff1a;由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序&#xff0c;负责提供用户界面和交互逻辑 &#xff0c;接收用户输入&#xff0c;向服务器发送请求&#xff0c;并展示服务…...

Java毕业设计:WML信息查询与后端信息发布系统开发

JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发&#xff0c;实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构&#xff0c;服务器端使用Java Servlet处理请求&#xff0c;数据库采用MySQL存储信息&#xff0…...

搭建DNS域名解析服务器(正向解析资源文件)

正向解析资源文件 1&#xff09;准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2&#xff09;服务端安装软件&#xff1a;bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...