JavaScript - 实现队列数据结构

286 阅读4分钟

队列数据结构

**队列是遵循先进先出(FIFO)原则的一组有序的项。队列在尾部添加新元素,并从顶部移除元素。最新添加的元素必须排在队列的末尾。

在我们的现实生活中,最常见的队列的例子就是排队。在电影院售票处,自助餐厅,超市收银台,我们都会排队。一个常见的例子就是打印队列,比如我们需要打印五份文档。我们会打开每个文档,然后点击打印按钮,每个文档都会被发送到打印队列,第一个发送到打印队列的文档会首先被打印,以此类推,直到打印完所有文档。

封装一个队列

我们可以使用数组来保存队列中的元素,当然为了在获取元素时更高效,我们使用一个对象来存储元素,其实对于队列的常用方法和栈很类似,只是添加和移除元素的原则不同。队列的常用方法如下:

  • enqueue(element(s)):向队列尾部添加一个(或多个)新的项。
  • dequeue():移除队列的第一项(即排在队列最前面的项)并返回被移除的元素。
  • peek():返回队列中第一个元素——最先被添加,也将是最先被移除的元素。队列不做任何变动(不移除元素,只返回元素信息)。
  • isEmpty():如果队列中不包含任何元素,返回 true, 否则返回 false。
  • size():返回队列包含的元素个数,与数组的 length 属性类似。
  • clear():清空队列

由于Queue类中的第一个索引值不一定是0,我们需要从索引值为lowestCount的位置开始迭代队列。

双端队列数据结构

双端队列(deque,或称 double-ended queue)是一种允许我们同时从前端和后端添加和移除元素的特殊队列。举个例子,在买票的时候,一个刚买了票的人如果只是还需要再问一些简单的信息,就可以直接回到队伍的头部,另外,在队伍的末尾的人如果赶时间,可以直接离开队伍。由于双端队列同时遵守了先进先出和后进先出原则,可以说它是把队列和栈结合的一种数据结构。

封装一个双端队列

双端队列包含队列的一些方法:isEmpty、clear、size、toString,由于双端队列允许在两端添加和移除元素,还会有以下几个方法:

  • addFront(element):在双端队列前端添加新的元素。
  • addBack(element):在双端队列后端添加新的元素。
  • removeFront():从双端队列前端移除第一个元素。
  • removeBack():从双端队列后端移除第一个元素。
  • peekFront():返回双端队列前端的第一个元素。
  • peekBack():返回双端队列后端的第一个元素。

使用队列和双端队列来解决问题

循环队列 --- 击鼓传花游戏

由于队列经常被应用在计算机领域和我们的现实生活中,就出现了一些队列的修改版本,这其中的一种叫作循环队列。循环队列的一个例子就是击鼓传花游戏(hot potato)。在这个游戏中,玩家围成一个圆圈,把花尽快地传递给旁边的人。某一时刻传花停止,这个时候花在谁手里,谁就退出圆圈、结束游戏。重复这个过程,直到只剩一个玩家(胜者)。

双端队列 --- 回文检查器

回文是正反都能读通的单词、词组、数或一系列字符的序列,例如madam或racecar。有不同的算法可以检查一个词组或字符串是否为回文。最简单的方式是将字符串反向排列并检查它和原字符串是否相同。如果两者相同,那么它就是一个回文。我们也可以用栈来完成,但是利用数据结构来解决这个问题的最简单方法是使用双端队列。