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

堆、栈和队列(数据结构)

堆、栈和队列(数据结构)

这里写目录标题

  • 堆、栈和队列(数据结构)
      • **栈**
      • **队列**
      • 堆(Heap)()
      • 队列(Queue)(FIFO)
      • 栈(Stack)(LIFO)
      • 总结
    • 堆、队列和栈的内存管理
      • 堆(Heap)
      • 堆内存管理
      • 队列(Queue)
      • 队列内存管理
      • 栈(Stack)
      • 栈内存管理
      • 总结

堆、栈和队列是三种常见的数据结构

标题
堆就像一个可以随时增减的垃圾箱。你可以随时往里面扔东西,也可以随时把不需要的东西拿出来。堆的大小可以根据需要进行扩展或收缩,这使得它非常适合用来存储那些大小不固定的数据,比如动态数组、链表、树和图等。堆的内存管理需要程序员手动进行,使用 malloc()calloc()realloc()free() 函数来分配和释放内存。

栈就像一叠盘子,你只能从最上面的盘子开始取盘子。这就是栈的工作原理。在栈中,数据是按照“最后放入的元素先被取出”的原则进行访问的。栈主要用于存储函数调用相关的数据,如局部变量、返回地址和参数等。栈的大小是固定的,由操作系统或编译器在程序启动时分配。栈的内存管理由编译器自动进行,程序员不需要手动分配和释放栈内存。

队列

队列就像一个排队的地方,新来的排在队伍的后面,先来的排在队伍的前面。这就是队列的工作原理。在队列中,元素按照它们被添加的顺序进行访问。队列主要用于实现先进先出(FIFO)的数据结构,常用于任务调度和消息传递。队列的内存通常是固定的,由操作系统或编译器管理。队列的内存管理也是由编译器自动进行的,程序员不需要手动分配和释放队列内存。

下面是对这三种数据结构的比较:

堆(Heap)()

  • 用途:堆主要用于实现优先队列和动态数据结构,如最大堆和最小堆。
  • 特性:堆是一种树形的数据结构,其中每个节点都有子节点。堆通常用于实现排序和优先级调度算法。
  • 操作:堆的操作包括插入(增加节点)和删除(减少节点)。
  • 访问顺序:堆中的元素可以根据其优先级进行访问,优先级高的元素先被访问。
  • 使用场景:优先队列、动态排序、算法实现(如Dijkstra算法)。

队列(Queue)(FIFO)

  • 用途:队列主要用于实现先进先出(FIFO)的数据结构,常用于任务调度和消息传递。
  • 特性:队列是一种线性数据结构,元素按顺序排列,新元素在队列的一端插入,而旧元素在另一端移除。
  • 操作:队列的操作包括入队(在队尾添加元素)和出队(在队头移除元素)。
  • 访问顺序:队列中的元素按照它们被添加的顺序进行访问。
  • 使用场景:任务调度、消息队列、缓存。
  • 两种常见的实现方式:
    1. 数组队列
      • 使用一个数组来存储队列中的元素。
      • 队头和队尾是数组中的两个指针,分别指向队列中第一个元素和最后一个元素的下一个位置。
      • 当队列满时,无法再添加新元素;当队列空时,没有元素可以取出。
    2. 链表队列
      • 使用链表来存储队列中的元素。
      • 链表中的每个节点包含一个数据元素和一个指向下一个节点的指针。
      • 队头和队尾也是两个指针,分别指向队列中第一个元素和最后一个元素的下一个位置。
      • 队列的大小可以根据需要动态变化,不像数组队列那样受限于数组的大小。

栈(Stack)(LIFO)

  • 用途:栈主要用于实现后进先出(LIFO)的数据结构,常用于函数调用、表达式求值和数据暂存。
  • 特性:栈是一种线性数据结构,元素按顺序排列,新元素在栈顶添加,旧元素在栈顶移除。
  • 操作:栈的操作包括压栈(在栈顶添加元素)和弹栈(从栈顶移除元素)。
  • 访问顺序:栈中的元素按照它们被添加的顺序进行访问。
  • 使用场景:函数调用、递归、后缀表达式求值。

总结

  • :用于实现优先队列和动态数据结构,操作复杂,适用于需要优先级排序的场景。
  • 队列:用于实现先进先出(FIFO)的数据结构,操作简单,适用于需要顺序处理的场景。
  • :用于实现后进先出(LIFO)的数据结构,操作简单,适用于需要后入先出的场景。
    每种数据结构都有其特定的应用场景和优势。在实际编程中,选择合适的数据结构可以大大提高程序的效率和性能。

堆、队列和栈的内存管理

堆(Heap)

  • 内存管理:堆是动态分配的内存区域,它允许程序在运行时请求任意大小的内存。堆上的内存由程序员手动管理,包括分配和释放。
  • 内存泄漏:由于堆上的内存需要程序员负责管理,如果程序员忘记释放不再需要的内存,就会导致内存泄漏。
  • 避免内存泄漏:为了避免内存泄漏,程序员应该在不再需要动态分配的内存时,使用 free() 函数将其释放。

堆内存管理

#include <stdio.h>
#include <stdlib.h>int main() {int *ptr;// 分配内存ptr = (int *)malloc(10 * sizeof(int));if (ptr == NULL) {// 内存分配失败exit(1);}// 使用内存for (int i = 0; i < 10; i++) {ptr[i] = i; // 初始化内存}// 释放内存free(ptr); // 释放内存return 0;
}

队列(Queue)

  • 内存管理:队列通常是基于数组或链表实现的,它们的内存管理方式与堆不同。队列的内存通常是固定的,由操作系统或编译器管理。
  • 内存泄漏:由于队列的内存通常是固定的,因此不太可能发生内存泄漏。
  • 避免内存泄漏:对于基于数组或链表的队列,通常不需要担心内存泄漏,因为它们的内存是由操作系统或编译器管理的。

队列内存管理

#include <stdio.h>
#include <stdlib.h>struct Node {int data;struct Node *next;
};int main() {struct Node *head = NULL, *newNode, *temp;// 动态分配内存newNode = (struct Node *)malloc(sizeof(struct Node));newNode->data = 1;newNode->next = NULL;head = newNode;// 使用队列while (1) {// 模拟队列操作}// 释放队列内存while (head != NULL) {temp = head;head = head->next;free(temp);}return 0;
}

栈(Stack)

  • 内存管理:栈是后进先出(LIFO)的数据结构,它由操作系统自动管理。栈的大小通常是固定的,不会在运行期间改变。
  • 内存泄漏:由于栈的内存是自动管理的,因此不太可能发生内存泄漏。
  • 避免内存泄漏:对于栈,通常不需要担心内存泄漏,因为它的内存是由操作系统管理的。

栈内存管理

#include <stdio.h>int main() {int a, b, c;// 局部变量a = 1;b = 2;c = a + b;// 栈上的变量在函数返回时自动销毁printf("c = %d\n", c);return 0;
}

总结

堆上的内存需要程序员手动管理,容易发生内存泄漏。为了避免内存泄漏,程序员应该在不再需要动态分配的内存时,使用 free() 函数将其释放。队列和栈的内存通常是自动管理的,因此不太可能发生内存泄漏。

在实际编程中,避免内存泄漏的最佳实践包括:

  • 对于堆内存,使用 malloc()calloc()realloc()free() 函数进行管理。
  • 对于队列和栈,通常不需要担心内存泄漏,因为它们的内存是由操作系统或编译器管理的。
  • 编写良好的代码,确保在不再需要内存时及时释放。
  • 使用内存泄漏检测工具来发现潜在的问题。
  • 遵循良好的编程习惯,如避免全局变量和静态变量,尽量使用局部变量和动态内存分配。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • PGCCC|【PostgreSQL】PCA+PCP+PCM等IT类认证申报个税退税指南
  • 【mysql】02在ubuntu24安装并配置mysql
  • 【区块链 + 智慧政务】澳门:智慧城市建设之证书电子化项目 | FISCO BCOS应用案例
  • 单元测试有什么好处呢?
  • 【代码随想录_Day30】1049. 最后一块石头的重量 II 494. 目标和 474.一和零
  • SpringBoot集成Sharding-JDBC-5.3.0实现按月动态建表分表
  • 采用自动微分进行模型的训练
  • 睡前故事—绿色科技的未来:可持续发展的梦幻故事
  • 数据建设实践之大数据平台(五)安装hive
  • 企业网络实验(vmware虚拟机充当DHCP服务器)所有IP全部保留,只为已知mac分配固定IP
  • 从产品手册用户心理学分析到程序可用性与易用性的重要区别
  • 启智畅想火车类集装箱号码识别技术,软硬件解决方案
  • 新一代大语言模型 GPT-5 对工作与生活的影响及应对策略
  • LDAPWordlistHarvester:基于LDAP数据的字典生成工具
  • django-ckeditor富文本编辑器
  • java架构面试锦集:开源框架+并发+数据结构+大企必备面试题
  • JS基础篇--通过JS生成由字母与数字组合的随机字符串
  • Mysql优化
  • socket.io+express实现聊天室的思考(三)
  • ubuntu 下nginx安装 并支持https协议
  • unity如何实现一个固定宽度的orthagraphic相机
  • 从tcpdump抓包看TCP/IP协议
  • 开年巨制!千人千面回放技术让你“看到”Flutter用户侧问题
  • 前端性能优化——回流与重绘
  • 前端知识点整理(待续)
  • 使用 Node.js 的 nodemailer 模块发送邮件(支持 QQ、163 等、支持附件)
  • 腾讯视频格式如何转换成mp4 将下载的qlv文件转换成mp4的方法
  • 推荐一个React的管理后台框架
  • 如何用纯 CSS 创作一个菱形 loader 动画
  • ​一些不规范的GTID使用场景
  • # 飞书APP集成平台-数字化落地
  • #100天计划# 2013年9月29日
  • #define 用法
  • #我与Java虚拟机的故事#连载03:面试过的百度,滴滴,快手都问了这些问题
  • (env: Windows,mp,1.06.2308310; lib: 3.2.4) uniapp微信小程序
  • (Matalb时序预测)PSO-BP粒子群算法优化BP神经网络的多维时序回归预测
  • (Redis使用系列) SpirngBoot中关于Redis的值的各种方式的存储与取出 三
  • (编程语言界的丐帮 C#).NET MD5 HASH 哈希 加密 与JAVA 互通
  • (第30天)二叉树阶段总结
  • (回溯) LeetCode 77. 组合
  • (贪心) LeetCode 45. 跳跃游戏 II
  • (学习日记)2024.03.25:UCOSIII第二十二节:系统启动流程详解
  • (转)编辑寄语:因为爱心,所以美丽
  • (转)程序员疫苗:代码注入
  • (轉貼)《OOD启思录》:61条面向对象设计的经验原则 (OO)
  • .apk 成为历史!
  • .bat批处理(三):变量声明、设置、拼接、截取
  • .NET WPF 抖动动画
  • .NET开发人员必知的八个网站
  • .secret勒索病毒数据恢复|金蝶、用友、管家婆、OA、速达、ERP等软件数据库恢复
  • /dev/sda2 is mounted; will not make a filesystem here!
  • @converter 只能用mysql吗_python-MySQLConverter对象没有mysql-connector属性’...
  • @Documented注解的作用
  • [1127]图形打印 sdutOJ
  • [2008][note]腔内级联拉曼发射的,二极管泵浦多频调Q laser——