[数据结构]动态顺序表的实现与应用

文章目录

  • 一、引言
  • 二、动态顺序表的基本概念
  • 三、动态顺序表的实现
    • 1、结构体定义
    • 2、初始化
    • 3、销毁
    • 4、扩容
    • 5、缩容
    • 5、打印
    • 6、增删查改
  • 四、分析动态顺序表
    • 1、存储方式
    • 2、优点
    • 3、缺点
  • 五、总结
    • 1、练习题
    • 2、源代码

一、引言

想象一下,你有一个箱子(静态顺序表),它的大小是固定的,你只能在这个箱子里面放东西或者拿出来,如果东西放不下了,箱子就满了,没办法再放更多。但现在,我们有了一种更灵活的箱子 —— 动态顺序表。这个箱子不仅能放东西,还能根据需要自动变大或变小,非常方便。

不过,要想玩转这个神奇的箱子,我们得先对里面的 “东西” (数据)的存放方式有所了解,也就是得熟悉数组和指针。如果你对这些还不太熟悉,别担心,我已经为你准备了一篇文章作为参考:传送门。读完之后,你会发现它们其实并不复杂。


二、动态顺序表的基本概念

动态顺序表,简单来说,就是一个可以 “长大” 或 “缩小” 的箱子。它不像静态顺序表那样一开始就确定了大小,而是根据我们需要存放的东西的多少来动态地调整自己的大小。

当我们往动态顺序表里放东西时,如果箱子满了,它就会自动去找一个更大的箱子,然后把原来的东西和新东西一起放进去。这个过程就像是我们换了一个更大的家,然后把所有家具都搬进去一样。

反过来,如果我们从动态顺序表里拿走了很多东西,箱子变得空荡荡的,那它也会考虑换个小点的箱子住,毕竟节省空间也是一种美德嘛。

总之,动态顺序表就是这样一个既智能又灵活的箱子,它能够帮助我们更加高效地管理和存储数据。

请添加图片描述


三、动态顺序表的实现

1、结构体定义

首先,我们需要定义一个结构体来表示动态顺序表,这个结构体将包含指向数组元素的指针、当前存储的元素数量以及分配的空间大小。

typedef int DataType;
typedef struct {DataType* arr;//指向动态数组的指针int size;//当前存储的元素个数int capacity;//当前动态数组的容量
}Seq;

2、初始化

初始化动态顺序表时,我们需要为其分配一个初始的空间大小,并设置当前存储的元素数量为0。

void Init(Seq* ps, int capacity)
{capacity == 0 ? capacity = 2 : capacity;DataType* pos = (DataType*)malloc(sizeof(DataType) * capacity);if (pos == NULL){fprintf(stderr, "内存分配失败\n");exit(EXIT_FAILURE);}ps->array = pos;ps->capacity = capacity;ps->size = 0;
}

3、销毁

使用完动态顺序表后,需要释放分配的内存,避免内存泄漏。

void Destroy(Seq* ps)
{if (ps == NULL)return;free(ps->array);ps->array = NULL;ps->capacity = 0;ps->size = 0;
}

4、扩容

当向动态顺序表中添加元素时,如果当前空间已满,则需要进行扩容操作。扩容通常会将容量加倍。

void Reserve(Seq* ps)
{if (ps->size == ps->capacity){int capacity = ps->capacity == 0 ? 2 : ps->capacity * 2;DataType* pos = (DataType*)realloc(ps->array, capacity * sizeof(DataType));if (pos == NULL){fprintf(stderr, "内存分配失败\n");exit(EXIT_FAILURE);}ps->array = pos;ps->capacity = capacity;}
}

5、缩容

当删除动态顺序表中的元素时,如果当前空间过大,则需要进行缩容操作。

void Shrink(Seq* ps)
{if (ps->capacity >= 64 && ps->size < ps->capacity / 2.5){int capacity = ps->capacity / 2;DataType* pos = (DataType*)realloc(ps->array, capacity * sizeof(DataType));if (pos == NULL){fprintf(stderr, "内存分配失败");exit(EXIT_FAILURE);}ps->array = pos;ps->capacity = capacity;}
}

5、打印

为了方便调试和查看动态顺序表中的内容,我们可以实现一个打印函数,将所有元素打印出来。

void Print(Seq* ps, void (*Pr) (DataType))
{for (int i = 0; i < ps->size; i++){Pr(ps->array[i]);}printf("NULL\n");
}

6、增删查改

实现顺序表的基本操作,让顺序表更具有实用性。

void PushFront(Seq* ps, DataType data)
{Insert(ps, 0, data);
}void PopFront(Seq* ps)
{Erase(ps, 0);
}void PushBack(Seq* ps, DataType data)
{Insert(ps, ps->size, data);
}void PopBack(Seq* ps)
{Erase(ps, ps->size - 1);
}void Insert(Seq* ps, int x, DataType data)
{assert(x >= 0 && x <= ps->size);Reserve(ps);for (int i = ps->size - 1; i >= x; i--){ps->array[i + 1] = ps->array[i];}ps->array[x] = data;ps->size++;
}void Erase(Seq* ps, int x)
{assert(ps != NULL && ps->size > 0 && x >= 0 && x < ps->size);for (int i = x; i < ps->size - 1; i++){ps->array[i] = ps->array[i + 1];}ps->size--;
}int Find(Seq* ps, DataType data)
{for (int i = 0; i < ps->size; i++){if (ps->array[i] == data){return i;}}return -1;
}void Modify(Seq* ps, int x, DataType data)
{assert(ps != NULL && ps->size > 0 && x >= 0 && x < ps->size);ps->array[x] = data;
}

四、分析动态顺序表

1、存储方式

顺序表是线性表的一种,线性表的逻辑结构是连续的,物理结构是不一定连续的。顺序表使用数组进行存储,数组在内存中是连续的,所以顺序表的物理结构是连续的。

2、优点

顺序表在随机访问时具有很高的效率,因为数组在内存中是连续的,所以可以通过下标直接访问到对应的元素。

3、缺点

顺序表在插入和删除元素时,需要移动大量元素,所以效率较低。另外,顺序表的大小是固定的,如果需要扩容,需要重新分配内存,这也会带来一定的开销。


五、总结

1、练习题

  • 移除元素
  • 合并两个有序数组
  • 盛水最多的容器
  • 接雨水
  • 合并区间
  • 插入区间

2、源代码

对于动态顺序表的源代码我已经开源在GItee:传送门
建议读者,仔细阅读源代码,理解数据结构的设计思路,尝试修改和扩展功能以加深理解。通过编写测试案例来验证理解和代码的正确性。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/146103.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【医学半监督】对比互补掩蔽的自监督预训练半监督心脏图像分割

SELF-SUPERVISED PRE-TRAINING BASED ON CONTRASTIVE COMPLEMENTARY MASKING FOR SEMI-SUPERVISED CARDIAC IMAGE SEGMENTATION 2024 IEEE International Symposium on Biomedical Imaging (ISBI) 摘要: 心脏结构分割对心脏病诊断非常重要,而使用大量注释的深度学习在这项任…

Buck变换器闭环控制,simulink仿真模型(适合初学者学习)

Buck变换器&#xff0c;又称为降压斩波器&#xff0c;是一种常见的DC-DC转换器&#xff0c;广泛应用于电源管理领域。它通过开关元件&#xff08;通常是MOSFET或BJT&#xff09;的导通与截止&#xff0c;改变输入电压到负载的平均电压&#xff0c;从而实现电压的降低。在实际应…

harbor私有镜像仓库,搭建及管理

私有镜像仓库 docker-distribution docker的镜像仓库&#xff0c;默认端口号5000 做个仓库&#xff0c;把镜像放里头&#xff0c;用什么服务&#xff0c;起什么容器 vmware公司在docker私有仓库的基础上做了一个web页面&#xff0c;是harbor docker可以把仓库的镜像下载到本地&…

tauri嵌入自定义目录/文件,并在代码中读取文件内容的操作流程

可以看官方文档&#xff1a;Embedding Additional Files | Tauri Apps 在绑定了文件之后&#xff0c;可以在js中访问嵌入的文件或者在rust中读取嵌入的文件内容&#xff0c;详细的配置操作如下。 在src-tauri中创建自定义文件夹或文件&#xff0c;并在在tauri.conf.json中配置…

Java多线程Thread及其原理深度解析

文章目录 1. 实现多线程的方式2. Thread 部分源码2.1. native 方法注册2.2. Thread 中的成员变量2.3. Thread 构造方法与初始化2.4. Thread 线程状态与操作系统状态2.4. start() 与 run() 方法2.5. sleep() 方法2.6. join() 方法2.7. interrupt() 方法 本文参考&#xff1a; 线…

Spring自定义参数解析器

在这篇文章中&#xff0c;我们认识了参数解析器和消息转换器&#xff0c;今天我们来自定义一个参数解析器。 自定义参数解析器 实现HandlerMethodArgumentResolver的类&#xff0c;并注册到Spring容器。 Component&#xff0f;&#xff0f;注册到Spring public class UserAr…

Java集合必知必会:热门面试题汇编与核心源码(ArrayList、HashMap)剖析

写在前面 &#x1f525;我把后端Java面试题做了一个汇总&#xff0c;有兴趣大家可以看看&#xff01;这里&#x1f449; ⭐️在无数次的复习巩固中&#xff0c;我逐渐意识到一个问题&#xff1a;面对同样的面试题目&#xff0c;不同的资料来源往往给出了五花八门的解释&#…

【Linux进程控制】自主Shell

目录 自主shell实现 获取基本变量 实现命令行 获取用户命令字符串 命令行字符串分割 内建命令CD() chdir getcwd putenv 检查是否为内建命令 检查是否为重定向 执行命令 主函数设置 测试用例 项目代码 自主shell实现 根据之前学的内容&#xff0c;我们已经可以模…

【学习笔记】SSL/TLS安全机制之CAA

1、概念界定 CAA全称Certificate Authority Authorization&#xff0c;即证书颁发机构授权&#xff0c;每个CA都能给任何网站签发证书。 2、CAA要解决的问题 例如&#xff0c;蓝色网站有一张橙色CA颁发的证书&#xff0c;我们也知道还有许多其他的CA&#xff1b;中间人可以说服…

网址链接能做成二维码吗?在线网址二维码生成的操作技巧

现在用二维码能够展示很多的内容&#xff0c;将内容放入二维码后&#xff0c;通过扫码的方式获取内容会更加的方便快捷&#xff0c;简化获取内容的流程。比如在分享网上内容时&#xff0c;可以将链接生成二维码的方式来让用户扫码访问网页&#xff0c;那么网址转二维码具体该怎…

【BetterBench博士】2024年中国研究生数学建模竞赛 E题:高速公路应急车道紧急启用模型 问题分析

2024年中国研究生数学建模竞赛 E题&#xff1a;高速公路应急车道紧急启用模型 问题分析 更新进展 【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析 【BetterBench博士】2024年中国研究生数学建模竞赛 E题&#xff1a;高速公路应急车道紧急启用…

【垃圾识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目选题+TensorFlow+图像识别

一、介绍 垃圾识别分类系统。本系统采用Python作为主要编程语言&#xff0c;通过收集了5种常见的垃圾数据集&#xff08;‘塑料’, ‘玻璃’, ‘纸张’, ‘纸板’, ‘金属’&#xff09;&#xff0c;然后基于TensorFlow搭建卷积神经网络算法模型&#xff0c;通过对图像数据集进…

Qt窗口——对话框

文章目录 对话框自定义对话框对话框分类消息对话框QMessageBox使用示例自定义按钮快速构造对话框 颜色对话框QColorDialog文件对话框QFileDialog字体对话框QFontDialog输入对话框QInputDialog 对话框 对话框可以理解成一个弹窗&#xff0c;用于短期任务或者简洁的用户交互 Qt…

2024华为杯研赛D题分析

2024华为杯研究生数学建模D题分析如下&#xff0c;完整版本在文末名片

【HTTP】请求“报头”,Referer 和 Cookie

Referer 描述了当前这个页面是从哪里来的&#xff08;从哪个页面跳转过来的&#xff09; 浏览器中&#xff0c;直接输入 URL/点击收藏夹打开的网页&#xff0c;此时是没有 referer。当你在 sogou 页面进行搜索时&#xff0c;新进入的网页就会有 referer 有一个非常典型的用…

扎克伯格的未来愿景:用智能眼镜引领数字社交新时代

Meta Connect 2024大会前夕&#xff0c;创始人马克扎克伯格的90分钟播客访谈&#xff0c;为我们描绘了Meta未来的蓝图。这场访谈&#xff0c;不仅是大会的热身&#xff0c;更是对科技未来的一次深刻洞察。 人工智能 - Ai工具集 - 未来办公人的智能办公生活导航网 扎克伯格的未…

nacos适配人大金仓的数据库

前言 在微服务架构中&#xff0c;服务发现和配置管理是关键组件。Nacos作为一个动态服务发现和配置管理平台&#xff0c;支持多种数据库作为其后端存储。本文将探讨如何在Nacos中适配人大金仓数据库&#xff0c;以及在此过程中的最佳实践。 Nacos简介 Nacos&#xff08;Nami…

二分查找算法(1) _二分查找_模板

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 二分查找算法(1) _二分查找模板 收录于专栏【经典算法练习】 本专栏旨在分享学习算法的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 1. 二…

Redis——持久化策略

Redis持久化 Redis的读写操作都是在内存上&#xff0c;所以Redis性能高。 但是当重启的时候&#xff0c;或者因为特殊情况导致Redis崩了&#xff0c;就可能导致数据的丢失。 所以Redis采取了持久化的机制&#xff0c;重启的时候利用之间持久化的文件实现数据的恢复。 Redis提…

[Matplotlib教程] 02 折线图、柱状图、散点图教程

基于MFCC和CNN的语音情感识别 2 折线图、柱状图、散点图2.1 折线图2.1.1 简单折线图2.1.1 线形和Markevery2.1.2 带误差棒的折线图2.1.3 区间填充和透明度 2.2 柱状图2.2.1 分组柱状图2.2.2 堆叠柱状图2.2.3 横向柱状图 2.3 散点图 我们的网站是 菜码编程&#xff0c;我们的q群…