【数据结构】顺序表:尾部操作我很行,随机访问我超快!!!
顺序表的模拟实现


文章目录
- 顺序表的模拟实现
- 1.线性表
- 2.顺序表
- 2.1概念结构
- 2.2顺序表的模拟实现
- 2.2.1顺序表的初始化
- 2.2.2顺序表的销毁
- 2.2.3尾插数据
- 2.2.4尾删数据
- 2.2.5头插数据
- 2.2.6头删数据
- 2.2.7中间插入数据
- 2.2.8中间删除数据
- 2.2.9打印顺序表
- 2.2.10查找数据
- 2.2.11复用Insert和Erase实现尾部操作和头部操作
- 2.3顺序表的优缺点
- 3.顺序表OJ题目训练
1.线性表
线性表 (linear list) 是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串…
线性表在逻辑结构是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,
💡ps:
逻辑结构:想象的该数据结构在内存中的存储方式,逻辑结构便于我们的思考。
物理结构:实际的该数据结构在内存中的存储方式。
例如,C语言中的二维数组
int arr[M][N]:逻辑结构:M行,N列的元素集合,不是连续存放的
物理结构:1行,M*N列的元素集合,是连续存放的
线性表在物理上存储时,通常以数组和链式结构的形式存储。

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

-
动态顺序表:使用动态开辟的数组存储。(malloc动态开辟空间)

2.2顺序表的模拟实现
静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小,所以下面我们实现动态顺序表。
SeqList.h中的声明(因为需要通过函数来修改顺序表,所以要传址)
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int SLDateType;//顺序表的成员
typedef struct SeqList
{SLDateType* a;//顺序表的首元素地址size_t size;//顺序表的数据个数size_t capacity;//顺序表的容量
}SL;void SLInit(SL* ps);//顺序表的初始化void SLDestroy(SL* ps);//顺序表的销毁//尾部操作
void SLPushBack(SL* ps, SLDateType x);//尾插
void SLPopBack(SL* ps);//尾删//头部操作
void SLPushFront(SL* ps, SLDateType x);//头插
void SLPopFront(SL* ps);//头删//中间
size_t SLFind(SL* ps, SLDateType x);//查找(返回下标)
void SLInsert(SL* ps, size_t pos, SLDateType x);//在pos前插入数据x
void SLErase(SL* ps, size_t pos);//删除pos处的数据void SLPrint(SL* ps);//打印顺序表
SeqList.c结构功能实现:
包含头文件#include"SeqList.h"
2.2.1顺序表的初始化
void SLInit(SL* ps)//顺序表的初始化
{assert(ps);ps->a = NULL;ps->size = 0;ps->capacity = 0;
}
2.2.2顺序表的销毁
💡ps:由于是动态开辟的空间,使用完要还给操作系统,不然会造成内存泄漏。
void SLDestroy(SL* ps)//顺序表的销毁
{assert(ps);free(ps->a);ps->a = NULL;ps->size = 0;ps->capacity = 0;
}
2.2.3尾插数据
void Enhance(SL* ps)
{size_t newcapacity = (ps->capacity == 0) ? 4 : ps->capacity * 2;//如果容量为0,开辟4,否则两倍开辟SLDateType* tmp = (SLDateType*)realloc(ps->a, sizeof(SLDateType)*newcapacity);//这里要考虑异地增容的情况if (tmp == NULL)//增容失败{perror("realloc fail\n");return;}else{ps->a = tmp;ps->capacity = newcapacity;}
}void SLPushBack(SL* ps, SLDateType x)//尾插
{assert(ps);//防止ps为空,进行断言//考虑增容if (ps->size == ps->capacity)//空间不足时需要增容{Enhance(ps);}ps->a[ps->size++] = x;
}
💡ps:顺序表插入操作都要检查是否需要增容
时间复杂度:O(1)
2.2.4尾删数据
void SLPopBack(SL* ps)//尾删
{assert(ps);assert(ps->size > 0);//顺序表为空,则不可继续再删除--(ps->size);
}
💡ps:顺序表的删除操作都要检查是是否为空顺序表
时间复杂度:O(1)
2.2.5头插数据
void SLPushFront(SL* ps, SLDateType x)//头插
{assert(ps);//考虑增容if (ps->size == ps->capacity){Enhance(ps);}//挪动数据size_t end = ps->size;while (end > 0){ps->a[end] = ps->a[end - 1];--end;}//插入数据ps->a[end] = x;++(ps->size);
}
💡ps:由于顺序表是连续存储的,在头部插入数据时,需要将整体数据向后挪动一次,再将数据插入到头部

时间复杂度:O(N)
2.2.6头删数据
void SLPopFront(SL* ps)//头删
{assert(ps);assert(ps->size > 0);//挪动数据--(ps->size);size_t begin = 0;while (begin < ps->size){ps->a[begin] = ps->a[begin + 1];++begin;}}
💡ps:头删数据,将后面的数据向前移动,将第一个数据覆盖即可

时间复杂度:O(N)
2.2.7中间插入数据
void SLInsert(SL* ps, size_t pos, SLDateType x)//中间插
{assert(ps);assert(pos >= 0 && pos <= ps->size);//==0是头插,等于ps->size是尾插//考虑增容if (ps->size == ps->capacity){Enhance(ps);}//挪动数据size_t cur = ps->size;while (cur > pos){ps->a[cur] = ps->a[cur - 1];--cur;}//插入ps->a[cur] = x;++(ps->size);}
💡ps:中间插入数据,同样也需要向后挪动数据
时间复杂度:O(N)
2.2.8中间删除数据
void SLErase(SL* ps, size_t pos)//中间删
{assert(ps);assert(pos >= 0 && pos < ps->size);//等于0相等于头删,等于ps->size-1等于尾删//assert(ps->size > 0);//对pos的检查,间接检查了size要大于0--(ps->size);size_t cur = pos;while (cur < ps->size){ps->a[cur] = ps->a[cur + 1];++cur;}
}
💡ps:中间删除数据,同样也需要向前挪动数据
时间复杂度:O(N)
2.2.9打印顺序表
void SLPrint(const SL* ps)//打印顺序表
{assert(ps);for (size_t i = 0; i < ps->size; ++i){printf("%d ", ps->a[i]);}printf("\n");
}
2.2.10查找数据
size_t SLFind(const SL* ps, SLDateType x)//查找(返回下标)
{assert(ps);for (size_t i = 0; i < ps->size; ++i){if (ps->a[i] == x){return i;}}return EOF;//找不到
}
2.2.11复用Insert和Erase实现尾部操作和头部操作
Insert和Erase功能中是包含了尾部操作和头部操作的,所以尾部操作和头部操作可以使用Insert和Erase来复用
void SLPushBack(SL* ps, SLDateType x)//尾插
{SLInsert(ps, ps->size, x);
}void SLPopBack(SL* ps)//尾删
{SLErase(ps, ps->size - 1);
}void SLPushFront(SL* ps, SLDateType x)//头插
{SLInsert(ps, 0, x);
}void SLPopFront(SL* ps)//头删
{SLErase(ps, 0);
}
2.3顺序表的优缺点
优点:
1. 尾插和尾删的效率很高,时间复杂度为:O(1)
2. 支持随机访问,知道了一个元素的下标,就可以直接访问和修改
缺点:
1. 头部操作和中间操作中,需要挪动数据,时间复杂度为:O(N),效率较低
2. 增容会带来一定的性能消耗,特别是异地增容,代价是极大的
3. 2倍增容方式,会有一部分的空间浪费
3.顺序表OJ题目训练
- 原地移除数组中所有的元素val,要求时间复杂度为O(N),空间复杂度为O(1)。OJ链接
- 删除排序数组中的重复项。OJ链接
- 合并两个有序数组。OJ链接
相关文章:
【数据结构】顺序表:尾部操作我很行,随机访问我超快!!!
顺序表的模拟实现 文章目录顺序表的模拟实现1.线性表2.顺序表2.1概念结构2.2顺序表的模拟实现2.2.1顺序表的初始化2.2.2顺序表的销毁2.2.3尾插数据2.2.4尾删数据2.2.5头插数据2.2.6头删数据2.2.7中间插入数据2.2.8中间删除数据2.2.9打印顺序表2.2.10查找数据2.2.11复用Insert和…...
SQL优化
SQL优化 SQL优化的方法: sql查询语句尽不使用select * ,而是具体的字段。 节约资源,减少网络开销。减少回表,提高查询效率。 避免在where子句中使用or来连接条件。 or可能会使索引失效,从而进行全表查询。 尽量使用…...
Java ArrayList 和 LinkList 原理对比
Java 中的 ArrayList 和 LinkedList 都是实现了 List 接口的集合类它们都允许添加、删除和修改元素。但是它们的底层实现原理不同导致它们在不同的场景下拥有不同的优劣势。 ArrayListArrayList 的底层是通过数组实现的因此它具有数组的特性。它允许快速随机访问元素但是在插入…...
【Spring】入门概述(一)
🚗Spring学习第一站~ 🚩本文已收录至专栏:Spring家族学习之旅 👍希望您能有所收获 一.初识 Spring并不是单一的一个技术,而是一个大家族,发展到今天已经形成了一种开发的生态圈,Spring提供了若…...
十二、面向切面编程AOP
IoC使软件组件松耦合。AOP让你能够捕捉系统中经常使用的功能,把它转化成组件。 AOP(Aspect Oriented Programming):面向切面编程,面向方面编程。(AOP是一种编程技术) AOP是对OOP的补充延伸。 …...
Mybatis 处理 CLOB/BLOB 类型数据
Mybatis 处理 CLOB/BLOB 类型数据 BLOB 和 CLOB 都是大型字段类型。 BLOB通过二进制存储,而CLOB可以直接存储文本。 通常,图片、文件、音乐等信息存储在 BLOB 字段中。首先,文件是转换为二进制,然后存储在。文章或较长的文本存…...
【NLP经典论文阅读】Efficient Estimation of Word Representations in Vector Space(附代码)
❤️觉得内容不错的话,欢迎点赞收藏加关注😊😊😊,后续会继续输入更多优质内容❤️👉有问题欢迎大家加关注私戳或者评论(包括但不限于NLP算法相关,linux学习相关,读研读博…...
Spring bean生命周期分为几个阶段?
bean 的生命周期从调用 beanFactory 的 getBean 开始,到这个 bean 被销毁,可以总结为以下七个阶段:处理名称,检查缓存→处理父子容器→处理 dependsOn→选择 scope 策略→创建 bean→类型转换处理→销毁 bean划分的阶段和名称并不…...
【基础算法】单链表的OJ练习(4) # 分割链表 # 回文链表 #
文章目录前言分割链表回文链表写在最后前言 本章的OJ练习相对前面的难度加大了,但是换汤不换药,还是围绕单链表的性质来出题的。我相信,能够过了前面的OJ练习,本章的OJ也是轻轻松松。 对于OJ练习(3):-> 传送门 <…...
SpringBoot整合定时任务和邮件发送(邮箱 信息轰炸 整蛊)
SpringBoot整合定时任务和邮件发送(邮箱 信息轰炸 整蛊) 目录SpringBoot整合定时任务和邮件发送(邮箱 信息轰炸 整蛊)1.概述2.最佳实践2.1创建项目引入依赖(mail)2.2 修改yml配置文件2.3 启动类添加EnableScheduling注解2.4 执行的…...
Arduino添加ESP32开发板
【2023年3月4日】 最近要在新电脑上安装Arduino,需要进行一些配置,正好记录一下! Arduino2.0.1 下的开发板添加操作。 ESP32开发板GitHub链接: GitHub - espressif/arduino-esp32: Arduino core for the ESP32Arduino core for…...
Mysql通配符的使用
LIKE操作符 通配符:用来匹配值的一部分的特殊字符。 搜索模式:由字面值,通配符或两者组合构成的搜索条件。 百分号(%)通配符 搜索模式使用例如下 SELECT prod_id, prod_name FROM products WHERE prod_name Like jet%; 这条子句表示&…...
RocketMQ-02
1. 案例介绍 1.1 业务分析 模拟电商网站购物场景中的【下单】和【支付】业务 ###1)下单 用户请求订单系统下单订单系统通过RPC调用订单服务下单订单服务调用优惠券服务,扣减优惠券订单服务调用调用库存服务,校验并扣减库存订单服务调用用户…...
深度学习卷积神经网络CNN之 VGGNet模型主vgg16和vgg19网络模型详解说明(理论篇)
1.VGG背景 2. VGGNet模型结构 3. 特点(创新、优缺点及新知识点) 一、VGG背景 VGGNet是2014年ILSVRC(ImageNet Large Scale Visual Recognition Challenge大规模视觉识别挑战赛)竞赛的第二名,解决ImageNet中的1000类图…...
三:BLE协议架构简介
低功耗蓝牙体系整体架构说明1. PHY(物理层)2. LL(链路层)3. HCI(主机与控制器通信接口)4. L2CAP(逻辑链路控制及适配协议)5. ATT(属性协议)6. GATT(通用属性规范)7. GAP(通用访问规范)8. SM(安全管理)整体架构说明 架构层说明PHY1. 物理层2. 控制射频的发送和接收LL1. 链路层2.…...
小型双轮差速底盘双灰度循迹功能的实现
1. 功能说明 在机器人车体上安装2个 灰度传感器 ,实现机器人按照下图所指定的路线进行导航运动,来模拟仓库物流机器人按指定路线行进的工作过程。 2. 使用样机 本实验使用的样机为R023e样机。 3. 功能实现 3.1 电子硬件 在这个示例中,我们采…...
电子签名?玩具罢了!
需要的前置知识:简单的canvas绘制线路过程 let canvas document.getElementById(id); //id为canvas标签元素的id,或通过其它方法获取标签 let ctx canvas.getContext(2d); //规定为2d绘制图片,即确定为2d画笔 ctx.strokeStyle "whit…...
【Spring Boot读取配置文件的方式】
Spring Boot 支持多种读取配置文件的方式,常用的方式有以下三种: application.properties: Spring Boot 默认会读取该文件作为应用的配置文件。可以在 src/main/resources 目录下创建该文件,并在其中配置应用的属性。 applicat…...
java学习路线规划
java学习路线规划 一、写在前面 兄弟,我整理了一下关于自己之前学习java的一些方向,给你归纳在这里,有空就来看看,希望对你有帮助。 二、java基础篇 1、认识java 了解java历史,大概看看发展史,安装…...
格密码学习笔记(二):连续极小、覆盖半径和平滑参数
文章目录最短距离和连续极小值距离函数和覆盖半径格的平滑参数致谢最短距离和连续极小值 除了行列式,格的另一个基本量是格上最短非零向量的长度,即格中最短距离,其定义为 λ1minx,y∈L,x≠y∥x−y∥minz∈L,z≠0∥z∥.\begin{aligned} …...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...
以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
云原生安全实战:API网关Kong的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关(API Gateway) API网关是微服务架构中的核心组件,负责统一管理所有API的流量入口。它像一座…...
c++第七天 继承与派生2
这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分:派生类构造函数与析构函数 当创建一个派生类对象时,基类成员是如何初始化的? 1.当派生类对象创建的时候,基类成员的初始化顺序 …...
WPF八大法则:告别模态窗口卡顿
⚙️ 核心问题:阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程,导致后续逻辑无法执行: var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题:…...
nnUNet V2修改网络——暴力替换网络为UNet++
更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...
【安全篇】金刚不坏之身:整合 Spring Security + JWT 实现无状态认证与授权
摘要 本文是《Spring Boot 实战派》系列的第四篇。我们将直面所有 Web 应用都无法回避的核心问题:安全。文章将详细阐述认证(Authentication) 与授权(Authorization的核心概念,对比传统 Session-Cookie 与现代 JWT(JS…...
【免费数据】2005-2019年我国272个地级市的旅游竞争力多指标数据(33个指标)
旅游业是一个城市的重要产业构成。旅游竞争力是一个城市竞争力的重要构成部分。一个城市的旅游竞争力反映了其在旅游市场竞争中的比较优势。 今日我们分享的是2005-2019年我国272个地级市的旅游竞争力多指标数据!该数据集源自2025年4月发表于《地理学报》的论文成果…...
