8月阅读周·秒懂算法:用常识解读数据结构与算法:用栈和队列打造优雅的代码

举报
叶一一 发表于 2024/08/26 14:12:30 2024/08/26
【摘要】 背景去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。没有计划的阅读,收效甚微。新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。这个“玩法”虽然常见且板正,但是有效,已经坚持阅读七个月。已读完书籍:《架构简洁之道》、《深入浅出的Node.js》、《你不知道的JavaScript(上卷)》、《你不知道的JavaScri...

背景

去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。

没有计划的阅读,收效甚微。

新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。

这个“玩法”虽然常见且板正,但是有效,已经坚持阅读七个月。

已读完书籍《架构简洁之道》、《深入浅出的Node.js》、《你不知道的JavaScript(上卷)》、《你不知道的JavaScript(中卷)》、《你不知道的JavaScript(下卷)》、《数据结构与算法JavaScript描述》、《WebKit技术内幕》、《前端架构:从入门到微前端》

当前阅读周书籍《秒懂算法:用常识解读数据结构与算法》

用栈和队列打造优雅的代码

栈和数组存储数据的方式一样,它们都只是元素的列表。不同之处在于栈的以下3个限制。

  • 数据只能从栈末插入。
  • 数据只能从栈末删除。
  • 只能读取栈的最后一个元素。

大多数计算机科学的文献会把栈的末尾称为栈顶,而把栈的开头称为栈尾。

向栈插入新值也称为压栈。

从栈顶移除元素称为出栈。因为栈的限制,所以只能从栈顶弹出数据。

压栈和出栈操作可以用LIFO形容,也就是“后进先出”(last in, first out)。最后一个压入栈的元素同时也是第一个被弹出的。

抽象数据类型

大多数编程语言的内置数据类型或者类中没有栈,你需要自行实现。

要创建一个栈,一般需要用某种内置数据结构来实际存储数据。下面是栈的一种使用数组的Ruby实现:

class Stack
  def initialize
    @data = []
  end
  def push(element)
    @data << element
  end
  def pop
    @data.pop
  end
  def read
    @data.last
  end
end

这个实现在一个名为@data的数组中存储数据。

实例化栈的时候,会自动建立一个空数组@data = []。这个栈会使用push方法向@data数组插入元素,使用pop方法从@data数组移除元素,使用read方法从@data数组读取元素。

但这样使用数组构建Stack类,该接口就会强制用户只能用有限方式访问数组。正常情况下,我们可以读取数组的任意索引。但通过栈接口使用数组就只能读取最后一个元素。插入数据和删除数据也是如此。

因此栈和数组并不是同类数据结构。数组可以直接访问计算机内存,并且内置于大多数编程语言中。而栈其实是限制访问数组的一组规则和过程,它让我们只能获得特定结果。

事实上,用什么数据结构来实现栈根本不重要。只要有一组数据以LIFO方式操作就足够了。至于使用数组还是其他内置数据结构来实现栈都无所谓。因此,栈属于所谓的抽象数据结构——也就是围绕其他内置数据结构构建的一组理论规则。

有一点需要指出:即便是内置数据结构也可能是抽象数据结构。即便某种编程语言实现了Stack类,栈仍然是一种概念,可以用不同数据结构实现。

队列

队列是另一种处理临时数据的数据结构。队列和栈在很多方面很相近,但二者处理数据的顺序不同。和栈一样,队列也是抽象数据结构。

第一个添加到队列中的元素也是第一个被移除的。这就是计算机科学家使用“FIFO”这一术语的原因:先进先出(first in, first out)。

队列的开头被称为前端,而结尾被称为后端。

和栈一样,队列也是有3条限制(与栈的限制不同)的数组。

  • 数据只能插入队列末尾(与栈一样)。
  • 只能从队列前端删除数据(与栈相反)。
  • 只能读取队列前端的数据(与栈相反)。

队列实现

前面讲过,队列是抽象数据结构。和许多其他抽象数据结构一样,大部分编程语言没有默认实现队列。下面是队列的一个Ruby实现:

class Queue
  def initialize
    @data = []
  end
  def enqueue(element)
    @data << element
  end
  def dequeue
    # Ruby的shift方法会移除并返回数组的第一个元素:
    @data.shift
  end
  def read
    @data.first
  end
end

和栈一样,Queue类也用一个限制数据操作的接口包装了数组。我们只能用特定方式处理数据。enqueue方法可以向数组末尾插入数据,而dequeue方法则会移除数组的第一个元素。read方法让我们可以读取数组的第一个元素。

总结

栈和队列本质上都是数组。

具体来说,栈和队列是处理临时数据的优雅方法。无论是操作系统架构,还是打印队列,抑或是遍历数据,都可以使用栈和队列作为临时容器,写出漂亮的算法。


作者介绍
非职业「传道授业解惑」的开发者叶一一。
《趣学前端》、《CSS畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏️ | 留言📝

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。