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

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

文章目录

  • 一、引言
  • 二、动态顺序表的基本概念
  • 三、动态顺序表的实现
    • 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:传送门
建议读者,仔细阅读源代码,理解数据结构的设计思路,尝试修改和扩展功能以加深理解。通过编写测试案例来验证理解和代码的正确性。


相关文章:

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

文章目录 一、引言二、动态顺序表的基本概念三、动态顺序表的实现1、结构体定义2、初始化3、销毁4、扩容5、缩容5、打印6、增删查改 四、分析动态顺序表1、存储方式2、优点3、缺点 五、总结1、练习题2、源代码 一、引言 想象一下&#xff0c;你有一个箱子&#xff08;静态顺序…...

Invalid Private Key, Not a valid string or uint8Array

报这种错误&#xff1a;一般在生成private key前面添加"0x"即可解决。我就是在私钥前面添加了"0x"解决了。 在学习web3时&#xff0c;使用助词生成的私钥&#xff0c;然后由私钥导出keystore就报错&#xff1a; ERROR Invalid Private Key, Not a valid …...

【Text2SQL】PET-SQL:在Spider基准测试中取得了SOTA

解读&#xff1a;PET-SQL: A Prompt-enhanced Two-stage Text-to-SQL Framework with Cross-consistency 这篇论文介绍了一个名为 PET-SQL 的文本到 SQL&#xff08;Text-to-SQL&#xff09;框架&#xff0c;旨在通过增强提示&#xff08;prompt&#xff09;和利用不同大型语言…...

python-3n+1数链/233

一&#xff1a;3n1数链题目描述 在计算机科学上&#xff0c;有很多类问题是无法解决的&#xff0c;我们称之为不可解决问题。然而&#xff0c;在很多情况下我们并不知道哪一类问题可以解决&#xff0c;哪一类问题不可解决。现在我们就有这样一个问题&#xff0c;问题如下&#…...

vue2基础系列教程之v-model及面试高频问题

v-model是表单组件里面的核心知识点&#xff0c;这个指令给我们写表单业务带来了很大的方便。 元素标签上的 v-model 指令用于双向绑定数据,它是一个语法糖&#xff0c;可以用于代替 v-bind:value 和 input 例如&#xff1a;<input v-model"message" placeholder…...

【高分系列卫星简介——高分一号(GF-1)】

高分一号卫星&#xff08;GF-1&#xff09; 高分一号&#xff08;GF-1&#xff09;是中国高分辨率对地观测系统&#xff08;简称“高分专项”&#xff09;的第一颗卫星&#xff0c;具有里程碑式的意义。以下是对高分一号卫星的详细介绍&#xff1a; 一、基本信息 发射时间&…...

Python基于TensorFlow实现时间序列循环神经网络回归模型(LSTM时间序列回归算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 随着信息技术的发展和传感器设备的广泛应用&#xff0c;时间序列数据的产生量急剧增加。无论是股市价格…...

springboot实战学习(6)(用户模块的登录认证)(初识令牌)(JWT)

接着上篇博客学习。上篇博客是在基本完成用户模块的注册接口的开发以及注册时的参数合法性校验的基础上&#xff0c;基本完成用户模块的登录接口的主逻辑。具体往回看了解的链接如下。 springboot实战学习笔记&#xff08;5&#xff09;(用户登录接口的主逻辑)-CSDN博客文章浏览…...

二叉树的顺序存储和基本操作实现

写代码&#xff1a;定义顺序存储的二叉树&#xff08;数组实现&#xff0c;树的结点从数组下标1开始存储&#xff09; 基于上述定义&#xff0c;写一个函数 int findFather ( i ) &#xff0c;返回结点 i 的父节点编号 基于上述定义&#xff0c;写一个函数 int leftChild ( i…...

python学习-10【模块】

1、认识模块 导入模块 使用 import 语句使用 from … import 语句 1、import modulename [as alias] modulename&#xff1a;表示要导入的模块名as alias&#xff1a;可选参数&#xff0c;为模块起的别名 2、from modulename import name modulename&#xff1a;模块名&#x…...

modbus调试助手/mqtt调试工具/超轻巧物联网组件/多线程实时采集/各种协议支持

一、前言说明 搞物联网开发很多年&#xff0c;用的最多的当属modbus协议&#xff0c;一个稳定好用的物联网组件是物联网平台持续运行多年的基石&#xff0c;所以这个物联网组件从一开始就定位于自研&#xff0c;为了满足各种场景的需求&#xff0c;当然最重要的一点就是大大提…...

数值计算 --- 平方根倒数快速算法(0x5f3759df,这是什么鬼!!!)

平方根倒数快速算法 --- 向Greg Walsh致敬&#xff01; 1&#xff0c;牛顿拉夫逊 已知x&#xff0c;要计算&#xff0c;假设的值为a&#xff0c;则&#xff1a; &#xff0c;&#xff08;式1&#xff09; 如果定义一个自变量为a的函数f(a): 则&#xff0c;令函数f(a)等于0的a就…...

迭代器和生成器的学习笔记

迭代器 Python 迭代器是一种对象&#xff0c;它实现了迭代协议&#xff0c;包括 __iter__() 和 __next__() 方法。迭代器可以让你在数据集中逐个访问元素&#xff0c;而无需关心数据结构的底层实现。与列表或其他集合相比&#xff0c;迭代器可以节省内存&#xff0c;因…...

ES5 在 Web 上的现状

最后一个支持 ES5 的浏览器 IE 11 在 2022 年被微软停止支持&#xff0c;那么今天 Web 上的 ES5 现状如何&#xff1f;在构建生产代码时&#xff0c;Web 开发者的最佳实践是什么&#xff1f; 本文将通过数据来回答这些问题&#xff0c;并基于这些数据为网站开发者和库作者提供一…...

人话学Python-循环语句

一&#xff1a;while语句 while语句的组成由判断条件和执行语句组成。当满足条件时会不断执行后续语句&#xff0c;然后再循环执行的语句结束之后再次回到条件判断&#xff0c;如此循环。 pos 0 ans 0 while pos < 6:ans pos * 4pos 1 print(ans)>>>84"&…...

初识模版!!

初识模版 1.泛型编程1.1 如何实现一个交换函数呢&#xff08;使得所有数据都可以交换&#xff09;&#xff1f;1.2 那可以不可以让编译器根据不同的类型利用该模子来生成代码呢&#xff1f; 2.模版类型2.1 模版概念2.2 函数模版的原理2.3 函数模板的实例化2.4 模板参数的匹配原…...

算法之数学--hash算法 2021-03-11(未完待续)

1.hash算法 刷出一道墙 题目描述 Time Limit: 2000 ms Memory Limit: 256 mb 在一面很长的墙壁上&#xff0c;工人们用不同的油漆去刷墙&#xff0c;然而可能有些地方刷过以后觉得不好看&#xff0c;他们会重新刷一下。有些部分因为重复刷了很多次覆盖了很多层油漆&#xff…...

DHCP工作原理

在学习之前先提出几个问题&#xff1a;什么是DHCP&#xff1f;为什么要使用DHCP&#xff1f;在什么场景中使用DHCP&#xff1f;DHCP报文的目的IP和目的MAC是多少&#xff1f;DHCP报文是基于UDP还是基于TCP&#xff1f;DHCP服务器返回的报文中都包含什么信息&#xff1f; DHCP&a…...

服务发现和代理实例的自动更新

☞ 返回总目录 1.服务发现的两种方式 StartFindService 方法 这是一个在后台启动的连续 “FindService” 活动&#xff0c;当服务实例的可用性发生变化时&#xff0c;会通过回调通知调用者。 它返回一个FindServiceHandle&#xff0c;可通过调用StopFindService来停止正在进行…...

Redis的三种持久化方法详解

Redis持久化机制详解 | JavaGuide Redis 不同于 Memcached 的很重要一点就是&#xff0c;Redis 支持持久化&#xff0c;而且支持 3 种持久化方式: 快照&#xff08;snapshotting&#xff0c;RDB&#xff09;只追加文件&#xff08;append-only file, AOF&#xff09;RDB 和 A…...

对称与负电源测试:动态直流电子负载的设计、原理与应用

1. 项目概述&#xff1a;对称与负电源的静态与动态直流负载在电子实验室里&#xff0c;测试一个电源的性能&#xff0c;尤其是它的动态响应能力&#xff0c;是件既基础又关键的事。我们常说的“直流电子负载”就是这个领域的核心工具。我之前设计并分享过一个用于正电源测试的静…...

3步解锁专业级MMD创作:Blender插件如何重塑二次元动画工作流

3步解锁专业级MMD创作&#xff1a;Blender插件如何重塑二次元动画工作流 【免费下载链接】blender_mmd_tools MMD Tools is a blender addon for importing/exporting Models and Motions of MikuMikuDance. 项目地址: https://gitcode.com/gh_mirrors/bl/blender_mmd_tools …...

ESP32多任务水位监测:从Arduino到ESP-IDF的FreeRTOS实战

1. 项目概述&#xff1a;从Arduino到ESP-IDF的跃迁去年我在做毕业设计时&#xff0c;为了搭建一个ESP32的传感器节点演示程序&#xff0c;第一次深入使用了FreeRTOS。那段时间&#xff0c;我几乎天天和任务调度、队列、信号量打交道&#xff0c;从最初的一头雾水到后来能流畅地…...

钱钟书《围城》第1-5章阅读笔记:一场关于人生困境的提前预演

前言 钱钟书先生的《围城》被誉为"新儒林外史"&#xff0c;是中国现代文学史上风格独特的讽刺经典。这部创作于20世纪40年代的长篇小说&#xff0c;以抗战初期为背景&#xff0c;通过主人公方鸿渐的人生轨迹&#xff0c;深刻揭示了知识分子群体的精神困境与人性弱点。…...

上线前最后一道防线,DeepSeek代码审查如何帮你拦截87%的CVE类缺陷?

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;上线前最后一道防线&#xff0c;DeepSeek代码审查如何帮你拦截87%的CVE类缺陷&#xff1f; 在软件交付生命周期末期&#xff0c;传统人工代码审计与通用SAST工具常因误报率高、上下文理解弱而漏检高危漏…...

C++ vector容器总结

vector基本概念功能&#xff1a;vector数据结构和数组非常相似&#xff0c;也称为单端数组vector与普通数组区别&#xff1a;不同之处在于数组是静态空间&#xff0c;而vector可以动态扩展动态扩展&#xff1a;并不是在原空间之后续接新空间&#xff0c;而是找更大的内存空间&a…...

INT8量化下TVA注意力对齐精度保障方案

重磅预告&#xff1a;本专栏将独家连载系列丛书《智能体视觉技术与应用》部分精华内容&#xff0c;该书是世界首套系统阐述“因式智能体”视觉理论与实践的专著&#xff0c;特邀美国 TypeOne 公司首席科学家、斯坦福大学博士 Bohan 担任技术顾问。Bohan先生师从美国三院院士、“…...

百度深度学习研究院的“叛将“,带着一颗芯片改变了中国智能驾驶——地平线余凯,从ImageNet冠军到征程出货1000万

大家好&#xff0c;我是写代码的篮球球痴。这篇文章跟我自己有点关系——我开的是理想汽车。理想的智驾系统 AD Pro&#xff0c;搭载的就是地平线征程 5 芯片。2026 年 1 月理想 AD Pro 4.0 推送&#xff0c;基于单颗征程 6M 实现了城市 NOA——这是行业里第一个用单颗 128TOPS…...

Unity3D深度纹理实战:手把手教你实现可交互的激光雷达扫描特效(附完整C#/Shader代码)

Unity3D深度纹理实战&#xff1a;手把手教你实现可交互的激光雷达扫描特效&#xff08;附完整C#/Shader代码&#xff09;在科幻题材的游戏开发中&#xff0c;激光雷达扫描特效是营造科技感的经典元素。从《赛博朋克2077》的战术目镜到《看门狗》的环境扫描&#xff0c;这种动态…...

Python strip 与 rstrip 函数区别

Python strip 与 rstrip 函数区别 文章目录Python strip 与 rstrip 函数区别一、核心作用二、基础语法三、基础使用示例四、指定删除特定字符五、常用业务场景一、核心作用 函数作用范围strip()移除字符串首尾空白字符rstrip()仅移除字符串右侧末尾字符&#xff0c;左侧保持不…...