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

小肥柴慢慢手写数据结构(C篇)(4-3 关于栈和队列的讨论)

小肥柴慢慢学习数据结构笔记(C篇)(4-3 关于栈和队列的讨论)

  • 目录
    • 1 双端栈/队列
    • 2 栈与队列的相互转化
      • 2-1 栈转化成队列
      • 2-2 队列转化成栈
    • 3 经典工程案例
      • 3-1 生产者和消费者模型(再次重温环形缓冲区)
      • 3-2 MapReduce中的缓冲区对<k,v>键值对排序
    • 4 小结

目录

(本帖主要从形态上讨论线性表的一些共有特性,不涉及具体的编码环节)

1 双端栈/队列

(1)一般形态的讨论:经过大量编程训练后,不禁会有疑问:
【Q】为何ArrayList,LinkedList,Stack、Queue这四种基本形态以及它们的变种被统称为“线性表”呢?涉及到“双端”话题时,又应该如何正确理解呢?

【A】很多文献中总是给出大量的理论化论述,但是我认为可以简单的归纳如下:
(1)一个线性表两头都能进出。(注意红色箭头代表的数据进出方向。)
(2)可灵活设定元素增长方向:两头向中间 or 中间向两头;当然,都要处理越界/碰头问题。
(3)人们也习惯将带回绕的线性表当做一个环来看待。(老生常谈的话题,后续看案例。)
在这里插入图片描述
在这里插入图片描述
此时,在翻看双向链表的示意图,是不是更有味道了?
在这里插入图片描述

2 栈与队列的相互转化

这是一对经典的面试问题,在Leecode上有对应练习,大家可以试试看。

2-1 栈转化成队列

【Q】给定两个栈,你能否组装成一个队列?
【A】设置一个栈作入队用,另一个栈作出队用:
(1)入队直接压到输入栈。
在这里插入图片描述
(2)出队时:
<1> 若输出栈为空则将输入栈的全部数据依次弹出并压入输出栈。
<2> 此时输出栈从栈顶往栈底的顺序就是队列从队首往队尾的顺序。
<3> 若输出栈不为空,直接弹出即可。
在这里插入图片描述

2-2 队列转化成栈

【Q】给你两个队列,你能否组装成一个栈?
【A1】常规解法
(1)queue1用于存储栈内的元素,queue2作为入栈操作的辅助队列。
(2)入栈操作时,首先将元素入队到queue2,然后将queue1的全部元素依次出队并入队到queue2,此时queue2的前端的元素即为新入栈的元素,再将queue1和queue2互换,则queue1的元素即为栈内的元素,queue1的前端和后端分别对应栈顶和栈底。
(3)由于每次入栈操作都确保queue1的前端元素为栈顶元素,因此出栈操作和获得栈顶元素操作都可以简单实现。出栈操作只需要移除queue1的前端元素并返回即可,获得栈顶元素操作只需要获得queue1的前端元素并返回即可(不移除元素)。
(4)由于queue1用于存储栈内的元素,判断栈是否为空时,只需要判断queue1是否为空即可。
在这里插入图片描述
在这里插入图片描述
【A2】实际上,使用一个队列亦可:循环排队。
在这里插入图片描述
在这里插入图片描述

3 经典工程案例

3-1 生产者和消费者模型(再次重温环形缓冲区)

(1)数据消费者从队列中读取新的数据。
(2)数据生产者从队列中写入新的数据。
(3)只要读写操作速度协调,必然可以一直复用这段缓存。(溢写,spill机制)
在这里插入图片描述
【注】实际上把这个ring撇直了也没有那么神秘,不是吗?

3-2 MapReduce中的缓冲区对<k,v>键值对排序

在这里插入图片描述
【Q1】设想现在给你一个Byte数组(线性数据结构)如何把<k1,v1> ~ <kn,vn>n个键值对数据存入其中?
【Q2】此时若直接排序会导致频繁的内存腾挪(联想动态数组时我们实现的resize操作?),如何避免?

【A】在实际工程设计中,将数据转化为两部分的组合:
(1) 固定长度的<k,v>键值对。
(2)非固定长度meta元数据段。
(3)<k,v>键值对还存储了meta的起始位置。

为了提高buffer的利用率,考虑使用环形buffer,那么:
(1)index = 0处就相当于一条分割线,称为赤道(equator)。
(2)<k,v>和meta都以equator为起点,分别朝两个方向存放数据。
在这里插入图片描述
盗一张图,更加形象的表达
在这里插入图片描述
【效果】
(1)排序时仅需要调整<k,v>的顺序即可,极大减少内存腾挪。
(2)排序完成后,外部读取数据时,采用间接寻址能够以正确的顺序获取到完整的数据集合。

4 小结

本节着墨不多,但我认为只要图画的清楚,看图就能彻底领悟线性表的精髓:任意进出元素的巧用!当然,如果后续补全了树状数组话题的讨论(包括堆和树,特别是N叉树的代表B/B+树),整个知识体系正常看就完备了。

相关文章:

  • CentOS 8 更换软件源
  • Ubuntu 22.04 无法进入图形界面的解决方法
  • 浅谈大语言模型(LLM)的微调与部署
  • centos 安装 php gmp 模块
  • YashanDB认证,YCA证书认证教程,免费证书,内含真题考试题库及答案——五分钟速成
  • 设备物联网无线通信,ESP32-C3芯片模组方案,智能化联动控制
  • 003-SpringCloud Alibaba-Nacos(配置中心)
  • python读取word文档 | AI应用开发
  • 22. 备忘录模式
  • 爬虫中一些有用的用法
  • 【ISP】对于ISP的关键算法补充
  • Python第十七课:卷积神经网络 | 计算机视觉之眼
  • Vue3接入谷歌邮箱登录功能
  • 打造智能钉钉机器人:借助智谱GLM-4-Flash实现高效智能回复(文末附源码)
  • 决策树,Laplace 剪枝与感知机
  • K8S学习之基础二十三:k8s的持久化存储之nfs
  • 【CXX】6 内置绑定
  • MongoDB 触发器实现教程
  • js和java中方法重载(js本身是不支持方法重载,方便对比学习)
  • 从零开始的python学习(五)P75+P76+P77+P78+P79+P80
  • icp网站/挖掘关键词的工具
  • Wordpress 报表的插件/seo刷点击软件
  • 代码重构网站/p站关键词排名
  • 怎么看一个网站是用模板什么做的/拓客引流推广
  • 网站技术可行性/邯郸百度推广公司
  • 广东省建设厅官方网站多少钱/互联网营销的方法有哪些