简单队列_数据结构的简要介绍:队列如何工作

简单队列

by Michael Olorunnisola

通过Michael Olorunnisola

数据结构的简要介绍:队列如何工作 (A Gentle Introduction to Data Structures: How Queues Work)

Black Friday’s right around the corner, and the new Microsoft Surface Studio out in stores (I’m a loyal windows guy ?). So let’s talk about everyone’s favorite shopping past-time: waiting in line. And that age-old data structure, the queue.

黑色星期五即将到来,新的Microsoft Surface Studio即将在商店中推出(我是忠实的Windows家伙?)。 因此,让我们谈谈过去每个人最喜欢的购物:排队等候。 那个古老的数据结构,即队列。

Feel free to share this post with your friends who’ll be heading out to get the latest and greatest. But be warned — people have been known to forget how queues work on Black Friday.

随时与您的朋友分享这篇文章,他们将前往获取最新和最伟大的信息。 但请注意,人们已经忘记了黑色星期五排队的工作方式。

Queue列 (Queues)

A queue is a line (yep, the same one from kindergarten…no cutting still!)

队列是一条线(是的,幼儿园的那一行…还没剪!)

Additions (enqueues) always add to the back of the line

添加剂( 入列 )总是添加到该行的后面

Removals (dequeues) always remove from the front of the line

去除( 出队 )总是从生产线的前端去除

Queues follow the pattern of First item In is the First item Out (FIFO).

队列跟随开始步骤项的模式I n是开始步骤项øUT(FIFO)。

用例范例 (Example use cases)
  • Resolving simultaneous server requests from multiple users, such as 3 people buying the last ticket for a plane at almost the same time

    解决多个用户同时发出的服务器请求,例如3个人几乎同时购买了飞机的最后一张机票
  • Queuing up data during a breadth-first search.

    广度优先搜索期间对数据进行排队。

Let’s tackle the first use case by helping Microsoft create a queue data structure to manage all their requests for the new Surface Studio. I’m too busy coding and writing these posts to go get one myself, so if you’re a Microsoft representative reading this, please feel free to ship one my way. ?

让我们通过帮助Microsoft创建队列数据结构来管理他们对新Surface Studio的所有请求,解决第一个用例。 我太忙于编写代码和编写这些帖子,以致无法获得自己的一份子,因此,如果您是Microsoft的代表,请阅读本文,请随时按我的方式发送。 ?

Before we get started, a quick note on JavaScript arrays. Similar to stacks, JavaScript arrays naturally have the functionality of a queue built in.

在开始之前,请先简要介绍一下JavaScript数组。 与堆栈类似,JavaScript数组自然具有内置队列的功能。

如何使用JavaScript数组表示队列 (How to represent queues using JavaScript arrays)

Enqueue adds to the back of the array:

入队添加到数组的后面:

Array.push(someVal)

Dequeue removes and returns first item in array:

出队删除并返回数组中的第一项:

Array.shift()

If for some reason you’re feeling rebellious (what coder doesn’t ?) you could add to the front of the array, then remove from the back.

如果由于某种原因您感到反叛(什么编码员没有?),可以将其添加到数组的前面,然后从后面删除。

Enqueue adds item to the front of the array:

Enqueue将项目添加到数组的前面:

Array.unshift(someVal)

Dequeue removes item from the back of the array:

出队从数组的后面删除项目:

Array.pop()

That said, for the sake of being thorough, you’re going to rebuild it using a JavaScript Object.

就是说,为了更全面,您将使用JavaScript对象重建它。

So first thing you need to do for Microsoft is to create the actual Queue where you’re going to hold the individual members who click the buy button on their website.

因此,对于Microsoft而言,您要做的第一件事是创建实际的队列,在该队列中,您将容纳单击其网站上的“购买”按钮的单个成员。

class Queue{  constructor(){    this._storage = {};    this._start = -1; //replicating 0 index used for arrays    this._end = -1; //replicating 0 index used for arrays  }    size(){   return this._end - this._start;  }}
let appleQueue = new Queue();

As a quick reminder the _ just means this is a private variable, and shouldn’t be accessed directly.

快速提醒一下,_表示这是一个私有变量,不应直接访问。

Unlike the stack data structure, where additions and removals happen on the same side, the nature of the queue requires us to keep track of both ends. Because of that, you create the start variable to always track the front of the queue, and the end variable to track the end of the queue.

堆栈数据结构不同, 堆栈数据结构在同一侧进行添加和删除,而队列的性质要求我们跟踪两端。 因此,您将创建开始变量以始终跟踪队列的开头,并创建结束变量以跟踪队列的结尾。

Lastly, the easiest way to keep track of a queue’s size (without creating an unnecessary counter variable) is to keep track of the difference between your start and end points.

最后,跟踪队列大小(不创建不必要的计数器变量)的最简单方法是跟踪起点和终点之间的差异。

First, you should create a way for people who click buy to be added to the queue. You can do this via the enqueue method:

首先,您应该为点击购买的用户创建一种添加到队列中的方法。 您可以通过enqueue方法执行此操作:

class Queue{  constructor(){    this._storage = {};    this._start = -1; //replicating 0 index used for arrays    this._end = -1; //replicating 0 index used for arrays  }    enqueue(val){    this._storage[++this._end] = val;          //++this._end just means increment the end variable first    //It's equivalent to    //this._end++   //->    //this._storage[this._end] = val;  }    size(){   return this._end - this._start;  }}
let microsoftQueue = new Queue();
microsoftQueue.enqueue("{user: ILoveWindows@gmail.com}")microsoftQueue.enqueue("{user: cortanaIsMyBestFriend@hotmail.com}")microsoftQueue.enqueue("{user: InternetExplorer8Fan@outlook.com}")microsoftQueue.enqueue("{user: IThrowApplesOutMyWindow@yahoo.com}")

Great! Now your microsoftQueue storage is going to look a little something like this:

大! 现在,您的microsoftQueue存储将看起来像这样:

{
0: "{email: ILoveWindows@gmail.com}"
1: "{email: cortanaIsMyBestFriend@hotmail.com}"
2: "{email: InternetExplorer8Fan@outlook.com}"
3: "{email: IThrowApplesOutMyWindow@yahoo.com}"
}

So a quick note on the way users are being represented above ({user: …}).

因此,请快速注意一下上面表示用户的方式({user:…})。

When a user clicks the buy button on the client side, they’re sending all their relevant information to the server, which will handle the request. When data is often exchanged between systems, such as the client and server side, it’s most commonly sent as JSON (JavaScript Object Notation), via Ajax.

当用户单击客户端上的“购买”按钮时,他们会将所有相关信息发送到服务器,服务器将处理该请求。 当数据被经常系统,例如在客户端和服务器端之间交换的,它的最常用发送作为JSON ( 的J ava 小号 CRIPTöbjectÑ浮选),经由Ajax的

This is similar to JavaScript objects, in that it’s just a stringified version of key-value pairs. For those not familiar with JavaScript, it’s similar to a dictionary or hash table (which we’ll get to later in this series). For more information about this , there’s a great post here on StackOverflow by Andreas Grech.

这类似于JavaScript对象,因为它只是键值对的字符串化版本。 对于不熟悉JavaScript的人来说,它类似于字典或哈希表(我们将在本系列的后面部分进行介绍)。 有关更多信息,有一个伟大的职位在这里 StackOverflow上由Andreas格列奇。

Now back to your queue.

现在回到您的队列。

Thanks to the queue you created, Microsoft now has an efficient way of tracking all of the people who have purchased the Surface Studio, and in chronological order in which they purchased it. To make sure these people are served in the correct order, you need to create an accurate dequeue method that keeps track of the order of the buyers, and removes them from the queue once they’ve been served.

由于您创建了队列,Microsoft现在有了一种有效的方式来跟踪所有购买Surface Studio的人,并按购买时间的顺序进行跟踪。 为确保按正确的顺序送达这些人,您需要创建一种准确的出队方法,该方法可以跟踪买家的订单,并在送达后将他们从队列中删除。

class Queue{  constructor(){    this._storage = {};    this._start = -1; //replicating 0 index used for arrays    this._end = -1; //replicating 0 index used for arrays  }    enqueue(val){    this._storage[++this._end] = val;   }
dequeue(){    if(this._end > this._start){ //check if there are values      let nextUp = this._storage[++this._start];      delete this._storage[this._start];      return nextUp;    }  }      size(){   return this._end - this._start;  }}
let microsoftQueue = new Queue();
microsoftQueue.enqueue("{user: ILoveWindows@gmail.com}")microsoftQueue.enqueue("{user: cortanaIsMyBestFriend@hotmail.com}")microsoftQueue.enqueue("{user: InternetExplorer8Fan@outlook.com}")microsoftQueue.enqueue("{user: IThrowApplesOutMyWindow@yahoo.com}")
//Function to send everyone their Surface Studio!let sendSurface = recepient => {   sendTo(recepient);}
//When your server is ready to handle this queue, execute this:
while(microsoftQueue.size() > 0){  sendSurface(microsoftQueue.dequeue());}

And there it is folks! Everyone who was waiting in the microsoftQueue now gets their awesome new Surface Studio thanks to you.

这里有乡亲! 现在,所有在microsoftQueue中等待的人都可以通过他们获得很棒的新Surface Studio。

To be thorough, there are definitely some quick optimizations that can make code work more logically.

彻底来说,肯定有一些快速的优化可以使代码更合理地工作。

  1. You can reset your start and end values to 0 once everyone in the queue has been served. It’s unlikely that your queue would ever hit the “max” JavaScript number, but it’s better to be safe than sorry.

    一旦队列中的每个人都得到服务,就可以将起始值和结束值重置为0。 您的队列不太可能达到“最大” JavaScript编号 ,但是安全起来总比后悔好。

  2. You can switch out the “ end > start check ” with the size method, thanks to 0 being evaluated as “false” due to JavaScript type coercion. Read all about it here.

    您可以使用size方法切换“ end> start check”,这是由于JavaScript类型强制将0评估为“ false”。 阅读有关它的所有内容。

dequeue(){    if(this.size()){ //0 is a falsey value...coerced to return false      let nextUp = this._storage[++this._start];      delete this._storage[this._start];
if(!this.size()){ //Recheck after incrementing (!0 == true)        this._start = -1;        this._end = -1;       }            return nextUp;    }}

And there you go, you’ve finished writing your basic Queue!

至此,您已经完成了基本队列的编写!

队列方法的时间复杂度分析 (A time complexity analysis on the queue methods)

Here’s the code again:

再次是下面的代码:

class Queue{  constructor(){    this._storage = {};    this._start = -1; //replicating 0 index used for arrays    this._end = -1; //replicating 0 index used for arrays  }    enqueue(val){    this._storage[++this._end] = val;   }
dequeue(){    if(this.size()){ /      let nextUp = this._storage[++this._start];      delete this._storage[this._start];
if(!this.size()){         this._start = -1;        this._end = -1;       }            return nextUp;    }  }    size(){   return this._end - this._start;  }}

The same logic for stacks also applies here:

堆栈的相同逻辑也适用于此处:

Enqueue (addition) is O(1). Since you’ll always know where the end of the queue is (thanks to your end variable), you don’t have to iterate to add an item.

入队 (加法)为O(1) 。 由于您将始终知道队列的结束位置(由于使用了end变量),因此不必重复添加项。

Dequeue (removal) is O(1). No iteration is necessary for removal since you always have the current start position.

出队 (移除)为O(1) 。 由于您始终具有当前起始位置,因此无需进行迭代就可以删除。

Size is O(1). The size is always known thanks to your start and end variables.

大小O(1) 。 由于您的开始和结束变量,大小始终是已知的。

One really important thing to note here is that queues aren’t meant to be infinite, although our queue class and JavaScript array will allow you to keep on adding items until the system runs out of memory.

这里要注意的一件非常重要的事情是,队列并不是无限的,尽管我们的队列类和JavaScript数组将允许您继续添加项目,直到系统内存不足为止。

One way to optimize is by making a space-limited array to create a circular queue. Damian Gordon provides a really good video walk-through on YouTube. This will also be handy for when we get to hash tables in future articles!

一种优化方法是通过创建一个空间受限的数组来创建循环队列。 Damian Gordon在YouTube上提供了非常不错的视频演示。 这对于以后的文章中的哈希表也非常有用!

是时候快速回顾一下 (Time for a quick recap)

Queues:

队列:

  1. Follow a First In First Out (FIFO) pattern

    遵循先进先出(FIFO)模式
  2. Have a start and end property to track the front and back of your queue

    有一个start和end属性来跟踪队列的前后
  3. Have an enqueue (add) and dequeue (remove) method to manage the contents of your queue

    具有入队(添加)和出队(删除)方法来管理队列的内容
  4. Have a size property that allows you to track how large your queue is

    具有size属性,可让您跟踪队列的大小

这是一个快速的挑战 (Here’s a quick challenge)

Using what you now know about Stacks and what you learned today about Queues, try re-implementing a Queue using just stacks.

使用您现在对堆栈的了解以及今天对队列的了解,尝试仅使用堆栈重新实现一个队列。

As a quick hint, you’ll only need two stacks.

快速提示,您只需要两个堆栈。

Thanks to Jason Holtkamp for coming up with this quick challenge!

感谢Jason Holtkamp提出了这一快速挑战!

进一步阅读 (Further reading)

Wikipedia as always ?

维基百科一如既往?

This Wikipedia article on priority queue. We’ll come back to this in future articles.

这篇有关优先级队列的维基百科文章 。 我们将在以后的文章中再次讨论。

A nice demo by Larry Serflaten on Khan Academy, where he uses push and pull in place of enqueue and dequeue.

Lhan Serflaten在可汗学院的一个不错的演示 ,他在其中使用推拉来代替入队和出队。

And here’s the Answer for the quick challenge. Only look at this after trying it out for a bit yourself. You can also check out Levent Divilioglu’s answer for a fantastic graphical representation.

这是快速挑战的答案 。 自己尝试一下后,再看一下。 您也可以查看Levent Divilioglu的答案,以出色的图形表示。

翻译自: https://www.freecodecamp.org/news/a-gentle-introduction-to-data-structures-how-queues-work-f8b871938e64/

简单队列

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值