数据结构 队列_数据结构101:队列

数据结构 队列

by Kevin Turney

凯文·特尼(Kevin Turney)

数据结构101:队列 (Data Structures 101: Queues)

从队列开始 (Starting with a Queue)

When you go the Shake Shack, most often there are other people on the line waiting to be served. The customers are arranged in a particular order, First In, First Out. Other real-life scenarios are toll booths or wedding chapels in Vegas. This method of ordering data for service, in our case, people, is what Queues are all about.

当您去Shake Shack时,通常会有其他人在排队等待服务。 客户按照特定的顺序排列,先入先出。 其他现实生活场景是拉斯维加斯的收费站或婚礼教堂。 在我们的情况下,这种为服务订购数据的方法就是人员,这就是队列的全部意义所在。

Queues are very similar to Stacks regarding interface, with the difference being Stacks process data Last In, First Out.

队列在接口方面与Stacks非常相似,区别在于Stacks处理数据的后进先出。

So we have differences in the order of processing — why? We need a different method of processing data that preserves the order. For example, suppose we have a stream of data in the node. As it comes in, we need to do something to it and then write it to a file to read later. For simplicity sake, let’s say we need to capitalize every letter streamed. What would happen if we used a LIFO, or stack data structure?

因此,我们在处理顺序上有差异-为什么? 我们需要一种不同的方法来处理保留订单的数据。 例如,假设我们在节点中有一个数据流。 传入时,我们需要对其进行处理,然后将其写入文件以供以后读取。 为了简单起见,假设我们需要大写每个流字母。 如果我们使用LIFO或堆栈数据结构会怎样?

The main reason is queues process data fairly and preserve the order of the collection. This also happens when we iterate over items with a for or while loop, forEach(), or map() method. Each item in the array gets processed in the order it was inserted, from index 0 to index.length — 1.

主要原因是将队列公平地处理数据并保留收集顺序。 当我们使用for或while循环,forEach()或map()方法迭代项目时,也会发生这种情况。 数组中的每个项目都按照插入顺序从索引0到index.length — 1进行处理。

In Queues, items are processed in the order they are inserted.

在队列中,按插入顺序处理项目。

实作 (Implementation)

A simple implementation using arrays is with the method shift() to remove from the front and unshift() to add the front.

使用数组的简单实现是使用shift()方法从最前面删除,而unshift()方法添加到最前面。

Like my post on Stacks, we will describe the API for a Queue. Then we’ll start with an implementation using the pseudoclassical method and a base object.

就像我在Stacks上的帖子一样,我们将描述Queue的API。 然后,我们将从使用伪古典方法和基础对象的实现开始。

When an item is inserted into a queue, it’s called enqueued. When an item is removed, it is dequeued. Other methods include peek, contains, until, and count.

将项目插入队列后,称为enqueued 。 删除项目后,该项目就会出队 。 其他方法包括窥视,包含,直到和计数。

To track our items, we use the head for the front of the queue and tail for the back. The difference between the two gives the queue size.

要跟踪我们的项目,我们将队列头部的前面放在头部,将队列后面放在后面。 两者之间的差异给出了队列大小。

Our Storage mechanism is as follows:

我们的存储机制如下:

// _underscores indicate "private variables" to other engineers
const Queue = function(capacity) {  this.storage = {};  this.capacity = capacity || Infinity;  this._head = 0;  this._tail = 0}
let q = new Queue();q; // Queue { storage: {}, capacity: Infinity, _head: 0, _tail: 0 }

To Enqueue:

入队:

Queue.prototype.enqueue = function(value) {  if (this.count() < capacity) {    this.storage[this._tail++] = value;    return this.count();  }  return "Max capacity reached, please remove a value before enqueuing"}

To Dequeue:

出队:

Queue.prototype.dequeue = function() {    if (this.count() === 0) {      return "Nothing in the queue";    }    else {      let element = this.storage[this._head];      delete this.storage[this._head];      if (this._head < this._tail) {        this._head++;      }      return element;    }}

The remaining API:

剩余的API:

Queue.prototype.peek = function() {  return this.storage[this._head]}
Queue.prototype.contains = function(value) {  for (let i = this._head; i < this._tail; i++) {    if (this.storage[i] === value) {      return true;    }  }  return false;}
Queue.prototype.until = function(value) {  for (let i = this._head; i < this._tail; i++) {    if (this.storage[i] === value){      return i - this._head + 1;    }  }  return null;}
Queue.prototype.count = function() {  return this._tail - this._head;}
let q = new Queue();q.enqueue('ww');q.enqueue('aa');q; // Queue {capacity: Infinity, storage: { 0: 'ww', 1: 'aa' }, _head: 0, _tail: 2 }q.enqueue('bb');q.peek(); // 'ww'q.dequeue(); // 'ww'q; //Queue {capacity: Infinity, storage: { 1: 'aa', 2: 'bb' }, _head: 1, _tail: 3 }q.contains('bb'); // trueq; //Queue {capacity: Infinity,storage: { 1: 'aa', 2: 'bb' }, _head: 1, _tail: 3 }q.until('bb'); // 2q.count(); // 2

Under the hood, we learned in my post on Stacks, that any time a function is called it creates an execution context and is allocated a stack frame on the execution stack. Is there anything similar in JavaSrcipt that utilizes Queues? Yes: the event loop.

在幕后,我们在Stacks上了解到,每当调用一个函数时,它就会创建一个执行上下文,并在执行堆栈上分配一个堆栈框架。 JavaSrcipt中是否有使用队列的类似内容? 是的:事件循环。

事件循环和队列 (The Event Loop and Queues)

Before we get to what the event loop is, we need to understand a few terms first.

在了解事件循环是什么之前,我们需要首先了解一些术语。

Concurrency — In computer science, parts of a computer program can run out of order without affecting the outcome. In the context of JavaScript, it refers to the event loop’s ability to execute callback functions after completing other work.

并发性 -在计算机科学中,计算机程序的某些部分可以按顺序运行而不会影响结果。 在JavaScript上下文中,它是指事件循环在完成其他工作之后执行回调函数的能力。

Runtime — the time in which a program is running.

运行时 -程序运行的时间。

Non-blocking vs. blocking — blocking is when the execution of a JavaScript program must wait until another part of the program is completed, sometimes non-JavaScript operations. Essentially, synchronous, do one thing at a time.p

非阻塞与阻塞 -阻塞是指JavaScript程序的执行必须等到程序的另一部分完成(有时是非JavaScript操作)时才执行。 本质上是同步的,一次只做一件事。

Non-blocking operations, on the other hand, work asynchronously. They employ callbacks that allow operations to continue, and when the work is completed, the callback associated with that particular function or event fires.

另一方面,非阻塞操作是异步工作的。 他们使用允许操作继续的回调,当工作完成时,与该特定函数或事件关联的回调将触发。

System kernel — is the central part of an Operating System. It manages the operations of the computer and memory and hardware, specifically the CPU. To be more efficient, the event loop offloads certain operations to the kernel.

系统内核 -是操作系统的核心部分。 它管理计算机,内存和硬件(特别是CPU)的操作。 为了提高效率,事件循环将某些操作转移给了内核。

现在到事件循环。 (Now to the event loop.)

JavaScript is a single threaded language. This means the flow of execution goes in order, and it does one thing at a time. Node.js is built off of the Chrome V8 engine, and it employs a continually spinning loop waiting for incoming connections.

JavaScript是一种单线程语言。 这意味着执行流程是有序的,并且一次只执行一件事。 Node.js是基于Chrome V8引擎构建的,它采用了不断旋转的循环来等待传入连接。

When an asynchronous function executes, it enters the event loop. A message associated with this function enters the message queue in the order it was received. Other functions already in the loop are executed or are processing. When the message is dequeued, the callback function executes and is placed on the execution stack.

执行异步函数时,它将进入事件循环。 与该功能关联的消息按接收顺序进入消息队列 。 循环中已经存在的其他功能正在执行或正在处理中。 消息出队后,回调函数将执行并放置在执行堆栈中。

All the while, the event loop keeps spinning, waiting for more connections. This is how queues are used behind the scenes in JavaScript.

一直以来,事件循环一直在旋转,等待更多连接。 这就是JavaScript在后台使用队列的方式。

时间复杂度 (Time complexity)

Queue operations are very efficient. Enqueue, Dequeue, Peek, and Count are the fastest working in constant time. Contains and Until take longer as our input size increases operating in linear time O(N);

队列操作非常有效。 入队,出队,查看和计数是恒定时间内最快的工作。 包含和直到随着输入大小的增加而花费更长的时间,线性时间为O(N);

Enqueue O(1)Dequeue O(1)Peek O(1)Count O(1)Contains O(N)Until O(N)

排队O(1)排队O(1)偷看O(1)计数O(1)包含O(N)直到O(N)

Thanks for reading. If you are unfamiliar with stacks, please check out my other article on them for more context.

谢谢阅读。 如果您不熟悉堆栈,请查看我的其他文章以获取更多背景信息。

翻译自: https://www.freecodecamp.org/news/data-structures-101-queues-a6960a3c98/

数据结构 队列

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值