和我一起学算法-队列

208 阅读3分钟

这是我参与2022首次更文挑战的第13天,活动详情查看:2022首次更文挑战」。

一、什么是队列

队列是一种先进先出的数据结构,就像排队买冰墩墩一样,先排队进店的人先买到

images.jpeg

在我们JavaScript中,是没有队列的,但是我们可以用Array来实现队列,我们可以用push和shift来实现队列先进先出的特性。

carbon.png

二、队列的应用场景

一句废话就是:所有需要先进先出的场景都需要队列。或者说是解决那种无法同时处理多个问题而需要一个一个来解决的场景时,我们也可以使用队列。

生活中常见的场景就是排队买冰墩墩,食堂排队打饭。

我们JS的异步任务队列,计算最近的请求次数。

三、计算最近的请求次数

这道题是leetcode第933题,题目如下:

image.png

这道题初次看肯定会十分蒙,但是当我们看解释是就会瞬间明白,就是看头部元素是不是在t-3000的范围内,如果不在就弹出该头部元素。这不就是队列的先进先出么!解法思路如下:

  • 声明一个队列
  • 队列push元素
  • 判断头部元素在不在t-3000范围内
  • 返回队列的长度 代码如下:

image.png

接下来我们分析一下上边这段代码的时间复杂度和空间复杂度。有一个while循环,需要往外弹出元素,所以时间复杂度是O(n),n是需要被踢出队列的请求的个数。我们声明了一个数组,那么空间复杂度也是O(n),n就是最近的请求次数。

四、js中的异步任务队列

image.png 谈这个问题的同时,我们要知道,

  • 当JavaScript代码执行时,会将不同的变量存放在内存的不同位置:堆和栈中。
  • 堆中存放着一些对象,栈中存放着基本类型的变量和对象的指针。
  • 当我们调用一个方法时,JS会生成一个与这个方法对应的执行环境,也叫做执行上下文。这个环境中存在着这个方法的私有作用域、方法的参数、这个作用域中定义的变量以及这个作用域的this对象。
  • 当一系列方法依次被调用时,由于JS是单线程的,同时只能执行一个,所以这些方法被放在一个单独的地方。这个地方就是执行栈。
  • 当一个Js脚本执行时,JS引擎会将其中的同步代码依次放到执行栈中,从头开始执行。直到执行完。
  • Js引擎遇到一个异步事件后并不会一直等待其返回结果,而是会将这个事件挂起,继续执行执行栈中的其他任务。当一个异步事件返回结果后,js会将这个事件加入与当前执行栈不同的另一个队列,我们称之为事件队列。
  • 被放入事件队列不会立刻执行其回调,而是等待当前执行栈中的所有任务都执行完毕, 主线程处于闲置状态时,主线程会去查找事件队列是否有任务。如果有,那么主线程会从中取出排在第一位的事件,并把这个事件对应的回调放入执行栈中,然后执行其中的同步代码,如此反复,这样就形成了一个无限的循环。整个的这种运行机制又称为Event Loop(事件循环)。

而这个事件队列我们就可以理解为异步任务队列。