如何在JavaScript中实现堆栈和队列?

Kin*_*tor 683 javascript queue stack data-structures

在JavaScript中实现Stack和Queue的最佳方法是什么?

我正在寻找分流码算法,我将需要这些数据结构.

Cor*_*lou 1249

var stack = [];
stack.push(2);       // stack is now [2]
stack.push(5);       // stack is now [2, 5]
var i = stack.pop(); // stack is now [2]
alert(i);            // displays 5

var queue = [];
queue.push(2);         // queue is now [2]
queue.push(5);         // queue is now [2, 5]
var i = queue.shift(); // queue is now [5]
alert(i);              // displays 2
Run Code Online (Sandbox Code Playgroud)

取自" 你可能不知道的9个javascript提示 "

  • 我建议使用queue.shift时要小心.IIRC不是O(1),而是O(n),如果队列变大,可能会太慢. (195认同)
  • 我会说这取决于javascript的实现.我不认为它是在javascript规范中定义的. (17认同)
  • 对于Queue性能问题,请参阅http://jsperf.com/queue-push-unshift-vs-shift-pop上三种不同类型的堆栈行为的比较 - 现在,如果只有某人足够好,可以包括转换那个包含@Gili提到的JS脚本的jsperf ...... (13认同)
  • 有关提高队列性能的简单实现,请参见http://code.stephenmorley.org/javascript/queues/. (9认同)
  • [我复活了博客文章](http://codetunnel.com/blog/post/9-javascript-tips-you-may-not-know)链接在这个答案中,因为archive.org并不总是最高效的.我更新了链接和图像以便它们可以工作,但我没有更改任何其他内容. (3认同)
  • Array.join()现在也比JS中通常的'+'慢,这是因为Array.join()没有收到那么多的优化更新,而'+'却得到了……我会研究所有这些技巧在使用它们之前 (2认同)

Rob*_*vey 81

Javascript具有push和pop方法,它们在普通的Javascript数组对象上运行.

对于队列,请看这里:

http://safalra.com/web-design/javascript/queues/

可以使用push和shift方法或者数组对象的unshift和pop方法在JavaScript中实现队列.虽然这是实现队列的一种简单方法,但对于大型队列来说效率非常低 - 因为方法在数组上运行,shift和unshift方法每次调用时都会移动数组中的每个元素.

Queue.js是一个简单而有效的JavaScript队列实现,其出队函数以分摊的常量时间运行.因此,对于较大的队列,它可能比使用数组快得多.

  • +1用于链接到延迟移位队列的实现 (8认同)
  • 您分享的链接具有检查基准测试结果的功能,在使用 Google Chrome 版本 59 进行测试时,我没有看到性能提升。 Queue.js 与它的速度不一致,但 Chrome 与它的速度非常一致。 (2认同)

Jan*_*nen 66

阵列.

堆:

var stack = [];

//put value on top of stack
stack.push(1);

//remove value from top of stack
var value = stack.pop();
Run Code Online (Sandbox Code Playgroud)

队列:

var queue = [];

//put value on end of queue
queue.push(1);

//Take first value from queue
var value = queue.shift();
Run Code Online (Sandbox Code Playgroud)

  • @MichaelGeller堆栈的顶部是Array的_last_元素.数组推送和弹出方法的行为就像一个堆栈. (16认同)
  • @MichaelGeller堆栈的行为是"先进先出".如果你使用JavaScript中的Array实现它的`push`和`pop`方法,那么问题就解决了.我真的没有在这里看到你的观点. (4认同)
  • @MichaelGeller 堆栈是概念性的。JS 数组是(除其他外)通过实现堆栈语义定义的堆栈。仅仅因为它也实现了数组语义并不会改变这一点。您可以像开箱即用的堆栈一样使用 JS 数组,在这种情况下,您推送和弹出的是“顶部”元素。 (2认同)

use*_*463 30

如果您想创建自己的数据结构,可以构建自己的数据结构:

var Stack = function(){
  this.top = null;
  this.size = 0;
};

var Node = function(data){
  this.data = data;
  this.previous = null;
};

Stack.prototype.push = function(data) {
  var node = new Node(data);

  node.previous = this.top;
  this.top = node;
  this.size += 1;
  return this.top;
};

Stack.prototype.pop = function() {
  temp = this.top;
  this.top = this.top.previous;
  this.size -= 1;
  return temp;
};
Run Code Online (Sandbox Code Playgroud)

对于队列:

var Queue = function() {
  this.first = null;
  this.size = 0;
};

var Node = function(data) {
  this.data = data;
  this.next = null;
};

Queue.prototype.enqueue = function(data) {
  var node = new Node(data);

  if (!this.first){
    this.first = node;
  } else {
    n = this.first;
    while (n.next) {
      n = n.next;
    }
    n.next = node;
  }

  this.size += 1;
  return node;
};

Queue.prototype.dequeue = function() {
  temp = this.first;
  this.first = this.first.next;
  this.size -= 1;
  return temp;
};
Run Code Online (Sandbox Code Playgroud)

  • 为了避免需要遍历整个事物以便追加到最后,通过this.last = node存储对最后一个的引用; (12认同)
  • 除非你有一个非常好的理由,否则永远不要实现这样的任何队列......虽然它看起来在逻辑上是正确的,但CPU并不是根据人类的抽象操作.对具有指针的数据结构进行迭代将导致CPU中的高速缓存未命中,这与高效的顺序数组不同.http://blog.davidecoppola.com/2014/05/cpp-benchmarks-vector-vs-list-vs-deque/ CPU憎恨激情指针 - 它们可能是缓存未命中的第一个原因并且必须访问来自RAM的内存. (9认同)
  • @cneuro与C++不同,JavaScript是一种垃圾收集语言.它有一个`delete`关键字,但这只对[将对象的属性标记为不存在 - 这与仅仅为属性分配'undefined`不同]有用(http://stackoverflow.com/a /四十二万九千○九十一分之一千四百九十六万七千五百六十八).JavaScript也有一个`new`操作符,但这只是用来在调用函数时将`this`设置为一个新的空对象.在C++中,你需要将每个`new`与`delete`配对,但不能在JavaScript中配对,因为GC.要停止在JavaScript中使用内存,只需停止引用该对象,它最终将被回收. (5认同)

Roh*_*hit 13

我的实施StackQueue使用Linked List

// Linked List
function Node(data) {
  this.data = data;
  this.next = null;
}

// Stack implemented using LinkedList
function Stack() {
  this.top = null;
}

Stack.prototype.push = function(data) {
  var newNode = new Node(data);

  newNode.next = this.top; //Special attention
  this.top = newNode;
}

Stack.prototype.pop = function() {
  if (this.top !== null) {
    var topItem = this.top.data;
    this.top = this.top.next;
    return topItem;
  }
  return null;
}

Stack.prototype.print = function() {
  var curr = this.top;
  while (curr) {
    console.log(curr.data);
    curr = curr.next;
  }
}

// var stack = new Stack();
// stack.push(3);
// stack.push(5);
// stack.push(7);
// stack.print();

// Queue implemented using LinkedList
function Queue() {
  this.head = null;
  this.tail = null;
}

Queue.prototype.enqueue = function(data) {
  var newNode = new Node(data);

  if (this.head === null) {
    this.head = newNode;
    this.tail = newNode;
  } else {
    this.tail.next = newNode;
    this.tail = newNode;
  }
}

Queue.prototype.dequeue = function() {
  var newNode;
  if (this.head !== null) {
    newNode = this.head.data;
    this.head = this.head.next;
  }
  return newNode;
}

Queue.prototype.print = function() {
  var curr = this.head;
  while (curr) {
    console.log(curr.data);
    curr = curr.next;
  }
}

var queue = new Queue();
queue.enqueue(3);
queue.enqueue(5);
queue.enqueue(7);
queue.print();
queue.dequeue();
queue.dequeue();
queue.print();
Run Code Online (Sandbox Code Playgroud)


kev*_*nyu 10

Javascript数组shift()特别是在持有许多元素时很慢.我知道两种方法来实现具有摊销的O(1)复杂性的队列.

首先是使用循环缓冲和表加倍.我以前实现过这个.你可以在这里看到我的源代码 https://github.com/kevyuu/rapid-queue

第二种方法是使用两个堆栈.这是具有两个堆栈的队列的代码

function createDoubleStackQueue() {
var that = {};
var pushContainer = [];
var popContainer = [];

function moveElementToPopContainer() {
    while (pushContainer.length !==0 ) {
        var element = pushContainer.pop();
        popContainer.push(element);
    }
}

that.push = function(element) {
    pushContainer.push(element);
};

that.shift = function() {
    if (popContainer.length === 0) {
        moveElementToPopContainer();
    }
    if (popContainer.length === 0) {
        return null;
    } else {
        return popContainer.pop();
    }
};

that.front = function() {
    if (popContainer.length === 0) {
        moveElementToPopContainer();
    }
    if (popContainer.length === 0) {
        return null;
    }
    return popContainer[popContainer.length - 1];
};

that.length = function() {
    return pushContainer.length + popContainer.length;
};

that.isEmpty = function() {
    return (pushContainer.length + popContainer.length) === 0;
};

return that;}
Run Code Online (Sandbox Code Playgroud)

这是使用jsPerf进行性能比较

CircularQueue.shift()vs Array.shift()

http://jsperf.com/rapidqueue-shift-vs-array-shift

正如您所看到的,使用大型数据集会明显加快速度


coy*_*508 10

如其他答案中所述,堆栈实现是微不足道的。

但是,我在这个线程中没有找到任何令人满意的答案来在 javascript 中实现队列,所以我自己做了一个。

此线程中有三种类型的解决方案:

  • 数组 - 最糟糕的解决方案,array.shift()在大型数组上使用效率非常低。
  • 链表 - 它是 O(1) 但为每个元素使用一个对象有点过分,特别是如果它们很多并且它们很小,比如存储数字。
  • 延迟移位数组 - 它包括将索引与数组相关联。当元素出队时,索引向前移动。当索引到达数组的中间时,数组被一分为二以去除前半部分。

延迟移位数组是我心目中最满意的解决方案,但它们仍将所有内容存储在一个大的连续数组中,这可能会出现问题,并且在对数组进行切片时应用程序会错开。

我使用小数组的链表(每个最多 1000 个元素)做了一个实现。数组的行为类似于延迟移位数组,只是它们从不切片:当数组中的每个元素都被删除时,数组会被简单地丢弃。

该软件包位于具有基本 FIFO 功能的npm上,我最近才推送它。代码分为两部分。

这是第一部分

/** Queue contains a linked list of Subqueue */
class Subqueue <T> {
  public full() {
    return this.array.length >= 1000;
  }

  public get size() {
    return this.array.length - this.index;
  }

  public peek(): T {
    return this.array[this.index];
  }

  public last(): T {
    return this.array[this.array.length-1];
  }

  public dequeue(): T {
    return this.array[this.index++];
  }

  public enqueue(elem: T) {
    this.array.push(elem);
  }

  private index: number = 0;
  private array: T [] = [];

  public next: Subqueue<T> = null;
}
Run Code Online (Sandbox Code Playgroud)

这是主Queue类:

class Queue<T> {
  get length() {
    return this._size;
  }

  public push(...elems: T[]) {
    for (let elem of elems) {
      if (this.bottom.full()) {
        this.bottom = this.bottom.next = new Subqueue<T>();
      }
      this.bottom.enqueue(elem);
    }

    this._size += elems.length;
  }

  public shift(): T {
    if (this._size === 0) {
      return undefined;
    }

    const val = this.top.dequeue();
    this._size--;
    if (this._size > 0 && this.top.size === 0 && this.top.full()) {
      // Discard current subqueue and point top to the one after
      this.top = this.top.next;
    }
    return val;
  }

  public peek(): T {
    return this.top.peek();
  }

  public last(): T {
    return this.bottom.last();
  }

  public clear() {
    this.bottom = this.top = new Subqueue();
    this._size = 0;
  }

  private top: Subqueue<T> = new Subqueue();
  private bottom: Subqueue<T> = this.top;
  private _size: number = 0;
}
Run Code Online (Sandbox Code Playgroud)

: X可以轻松删除类型注释 ( ) 以获取 ES6 javascript 代码。


May*_*ula 9

我认为实现堆栈和队列的最干净的方法应该是使用一个允许从两端添加和删除的容器,然后限制其一端的功能,这可以通过 JavaScript 中的一个简单数组来完成。

//封装时在堆栈容器中使用的语句

// Allow push and pop from the same end
array.push(element);
array.pop();
Run Code Online (Sandbox Code Playgroud)

//封装时在队列容器中使用的语句

// Allow push and pop from different ends
array.push(element);
array.shift();
Run Code Online (Sandbox Code Playgroud)


Ani*_* K. 8

您可以通过多种方式在Javascript中实现堆栈和队列.上面的大多数答案是非常浅的实现,我会尝试实现更可读的东西(使用es6的新语法功能)和健壮.

这是堆栈实现:

class Stack {
  constructor(...items){
    this._items = []

    if(items.length>0)
      items.forEach(item => this._items.push(item) )

  }

  push(...items){
    //push item to the stack
     items.forEach(item => this._items.push(item) )
     return this._items;

  }

  pop(count=0){
    //pull out the topmost item (last item) from stack
    if(count===0)
      return this._items.pop()
     else
       return this._items.splice( -count, count )
  }

  peek(){
    // see what's the last item in stack
    return this._items[this._items.length-1]
  }

  size(){
    //no. of items in stack
    return this._items.length
  }

  isEmpty(){
    // return whether the stack is empty or not
    return this._items.length==0
  }

  toArray(){
    return this._items;
  }
}
Run Code Online (Sandbox Code Playgroud)

这就是你如何使用堆栈:

let my_stack = new Stack(1,24,4);
// [1, 24, 4]
my_stack.push(23)
//[1, 24, 4, 23]
my_stack.push(1,2,342);
//[1, 24, 4, 23, 1, 2, 342]
my_stack.pop();
//[1, 24, 4, 23, 1, 2]
my_stack.pop(3)
//[1, 24, 4]
my_stack.isEmpty()
// false
my_stack.size();
//3
Run Code Online (Sandbox Code Playgroud)

如果您想查看有关此实现的详细说明以及如何进一步改进,可以在此处阅读:http://jschap.com/data-structures-in-javascript-stack/

这是es6中队列实现的代码:

class Queue{
 constructor(...items){
   //initialize the items in queue
   this._items = []
   // enqueuing the items passed to the constructor
   this.enqueue(...items)
 }

  enqueue(...items){
    //push items into the queue
    items.forEach( item => this._items.push(item) )
    return this._items;
  }

  dequeue(count=1){
    //pull out the first item from the queue
    this._items.splice(0,count);
    return this._items;
  }

  peek(){
    //peek at the first item from the queue
    return this._items[0]
  }

  size(){
    //get the length of queue
    return this._items.length
  }

  isEmpty(){
    //find whether the queue is empty or no
    return this._items.length===0
  }
}
Run Code Online (Sandbox Code Playgroud)

以下是如何使用此实现:

let my_queue = new Queue(1,24,4);
// [1, 24, 4]
my_queue.enqueue(23)
//[1, 24, 4, 23]
my_queue.enqueue(1,2,342);
//[1, 24, 4, 23, 1, 2, 342]
my_queue.dequeue();
//[24, 4, 23, 1, 2, 342]
my_queue.dequeue(3)
//[1, 2, 342]
my_queue.isEmpty()
// false
my_queue.size();
//3
Run Code Online (Sandbox Code Playgroud)

要了解如何实现这些数据结构以及如何进一步改进这些数据结构的完整教程,您可能需要浏览jschap.com上的"在javascript中使用数据结构"系列.这是队列的链接 - http://jschap.com/playing-data-structures-javascript-queues/


jfo*_*rjs 7

您可以根据此概念使用自己的自定义类,这里是您可以用来完成工作的代码段

/*
*   Stack implementation in JavaScript
*/



function Stack() {
  this.top = null;
  this.count = 0;

  this.getCount = function() {
    return this.count;
  }

  this.getTop = function() {
    return this.top;
  }

  this.push = function(data) {
    var node = {
      data: data,
      next: null
    }

    node.next = this.top;
    this.top = node;

    this.count++;
  }

  this.peek = function() {
    if (this.top === null) {
      return null;
    } else {
      return this.top.data;
    }
  }

  this.pop = function() {
    if (this.top === null) {
      return null;
    } else {
      var out = this.top;
      this.top = this.top.next;
      if (this.count > 0) {
        this.count--;
      }

      return out.data;
    }
  }

  this.displayAll = function() {
    if (this.top === null) {
      return null;
    } else {
      var arr = new Array();

      var current = this.top;
      //console.log(current);
      for (var i = 0; i < this.count; i++) {
        arr[i] = current.data;
        current = current.next;
      }

      return arr;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

并使用您的控制台进行检查,然后逐行尝试这些方法。

>> var st = new Stack();

>> st.push("BP");

>> st.push("NK");

>> st.getTop();

>> st.getCount();

>> st.displayAll();

>> st.pop();

>> st.displayAll();

>> st.getTop();

>> st.peek();
Run Code Online (Sandbox Code Playgroud)

  • 下注命名约定:以大写字母开头的方法(假定是构造方法)。 (2认同)

小智 6

/*------------------------------------------------------------------ 
 Defining Stack Operations using Closures in Javascript, privacy and
 state of stack operations are maintained

 @author:Arijt Basu
 Log: Sun Dec 27, 2015, 3:25PM
 ------------------------------------------------------------------- 
 */
var stackControl = true;
var stack = (function(array) {
        array = [];
        //--Define the max size of the stack
        var MAX_SIZE = 5;

        function isEmpty() {
            if (array.length < 1) console.log("Stack is empty");
        };
        isEmpty();

        return {

            push: function(ele) {
                if (array.length < MAX_SIZE) {
                    array.push(ele)
                    return array;
                } else {
                    console.log("Stack Overflow")
                }
            },
            pop: function() {
                if (array.length > 1) {
                    array.pop();
                    return array;
                } else {
                    console.log("Stack Underflow");
                }
            }

        }
    })()
    // var list = 5;
    // console.log(stack(list))
if (stackControl) {
    console.log(stack.pop());
    console.log(stack.push(3));
    console.log(stack.push(2));
    console.log(stack.pop());
    console.log(stack.push(1));
    console.log(stack.pop());
    console.log(stack.push(38));
    console.log(stack.push(22));
    console.log(stack.pop());
    console.log(stack.pop());
    console.log(stack.push(6));
    console.log(stack.pop());
}
//End of STACK Logic

/* Defining Queue operations*/

var queue = (function(array) {
    array = [];
    var reversearray;
    //--Define the max size of the stack
    var MAX_SIZE = 5;

    function isEmpty() {
        if (array.length < 1) console.log("Queue is empty");
    };
    isEmpty();

    return {
        insert: function(ele) {
            if (array.length < MAX_SIZE) {
                array.push(ele)
                reversearray = array.reverse();
                return reversearray;
            } else {
                console.log("Queue Overflow")
            }
        },
        delete: function() {
            if (array.length > 1) {
                //reversearray = array.reverse();
                array.pop();
                return array;
            } else {
                console.log("Queue Underflow");
            }
        }
    }



})()

console.log(queue.insert(5))
console.log(queue.insert(3))
console.log(queue.delete(3))
Run Code Online (Sandbox Code Playgroud)


njl*_*son 6

正如许多人所说:原生数组pushpop作为堆栈操作很好,但用作shift队列提取操作意味着数组中剩余的元素需要移动,这可能会很慢。在kevinyu 的答案中使用两个堆栈来创建队列的想法是修复它的好主意,当然这也可以使用本机数组堆栈来完成。(注意:实际上Yuki-Dreamer 已经有一个答案可以做到这一点,尽管比我的版本不那么紧凑。)

这是一个使用一些 ES5/ES6 功能的紧凑实现,它使队列对象的行为尽可能接近本机push/shift变体,除了每个操作需要摊销 O(1) 时间:

const queue = () => {
    const a = [], b = [];
    return {
        push: (...elts) => a.push(...elts),
        shift: () => {
            if (b.length === 0) {
                while (a.length > 0) { b.push(a.pop()) }
            }
            return b.pop();
        },
        get length() { return a.length + b.length }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在你可以这样做:

const q = queue();
q.push(8);
q.push(9);
q.push(10);
console.log(q.length);          // outputs 3
console.log(q.shift());         // outputs 8
q.push(11);
console.log(q.shift());         // outputs 9
console.log(q.shift());         // outputs 10
console.log(q.shift());         // outputs 11
console.log(q.shift());         // outputs undefined
Run Code Online (Sandbox Code Playgroud)

queue实现使用 的getter语法length,使其看起来像一个属性,并使用 Push的剩余参数语法,以允许一次推送多个内容。如果您不想这样做,可以将第 4 行替换为push: elt => a.push(elt),。(但是请注意,您不能我自己首先尝试的那样将其替换为push: a.push,非常奇怪的结果:这是因为它会导致调用本机推送方法并将其设置this为队列对象。)

优化:这是代码速度的微小改进。将该while行替换为以下两行,以便在每次从ato传输时保存一次推送+弹出操作b

                while (a.length > 1) { b.push(a.pop()) }
                return a.pop();
Run Code Online (Sandbox Code Playgroud)


Ni3*_*Ni3 5

否则,您可以使用两个数组来实现队列数据结构.

var temp_stack = new Array();
var stack = new Array();

temp_stack.push(1);
temp_stack.push(2);
temp_stack.push(3);
Run Code Online (Sandbox Code Playgroud)

如果我现在弹出元素,那么输出将是3,2,1.但我们需要FIFO结构,因此您可以执行以下操作.

stack.push(temp_stack.pop());
stack.push(temp_stack.pop());
stack.push(temp_stack.pop());

stack.pop(); //Pop out 1
stack.pop(); //Pop out 2
stack.pop(); //Pop out 3
Run Code Online (Sandbox Code Playgroud)


sny*_*rgd 5

这是一个相当简单的队列实现,有两个目的:

  • 与array.shift()不同,您知道此dequeue方法需要恒定时间(O(1)).
  • 为了提高速度,此方法使用的链接比链接列表方法少得多.

堆栈实现仅共享第二个目标.

// Queue
function Queue() {
        this.q = new Array(5);
        this.first = 0;
        this.size = 0;
}
Queue.prototype.enqueue = function(a) {
        var other;
        if (this.size == this.q.length) {
                other = new Array(this.size*2);
                for (var i = 0; i < this.size; i++) {
                        other[i] = this.q[(this.first+i)%this.size];
                }
                this.first = 0;
                this.q = other;
        }
        this.q[(this.first+this.size)%this.q.length] = a;
        this.size++;
};
Queue.prototype.dequeue = function() {
        if (this.size == 0) return undefined;
        this.size--;
        var ret = this.q[this.first];
        this.first = (this.first+1)%this.q.length;
        return ret;
};
Queue.prototype.peek = function() { return this.size > 0 ? this.q[this.first] : undefined; };
Queue.prototype.isEmpty = function() { return this.size == 0; };

// Stack
function Stack() {
        this.s = new Array(5);
        this.size = 0;
}
Stack.prototype.push = function(a) {
        var other;
    if (this.size == this.s.length) {
            other = new Array(this.s.length*2);
            for (var i = 0; i < this.s.length; i++) other[i] = this.s[i];
            this.s = other;
    }
    this.s[this.size++] = a;
};
Stack.prototype.pop = function() {
        if (this.size == 0) return undefined;
        return this.s[--this.size];
};
Stack.prototype.peek = function() { return this.size > 0 ? this.s[this.size-1] : undefined; };
Run Code Online (Sandbox Code Playgroud)


Red*_*edu 5

答案有点晚了,但我认为这个答案应该在这里。这是使用稀疏数组幂的 O(1)enqueue和 O(1)队列实现。dequeue

JS 中的稀疏数组大多被忽视,但它们实际上是一个宝石,我们应该在一些关键任务中使用它们的力量。

所以这里是一个框架Queue实现,它扩展了Array类型并一直在 O(1) 中完成它的事情。

class Queue extends Array {
  constructor(){
    super()
    Object.defineProperty(this,"head",{ value   : 0
                                      , writable: true
                                      });
  }
  enqueue(x) {
    this.push(x);
    return this;
  }
  dequeue() {
    var first;
    return this.head < this.length ? ( first = this[this.head]
                                     , delete this[this.head++]
                                     , first
                                     )
                                   : void 0; // perfect undefined
  }
  peek() {
    return this[this.head];
  }
}

var q = new Queue();
console.log(q.dequeue());      // doesn't break
console.log(q.enqueue(10));    // add 10
console.log(q.enqueue("DIO")); // add "DIO" (Last In Line cCc R.J.DIO reis cCc)
console.log(q);                // display q
console.log(q.dequeue());      // lets get the first one in the line
console.log(q.dequeue());      // lets get DIO out from the line
Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper {
  max-height: 100% !important;
}
Run Code Online (Sandbox Code Playgroud)

那么这里是否存在潜在的内存泄漏?不,我不这么认为。JS 稀疏数组是不连续的。因此,删除的项目不应成为数组内存占用的一部分。让 GC 为您完成它的工作。它是免费的。

一个潜在的问题是,length当您不断将项目放入队列时,该属性会无限增长。然而,仍然可以实现自动刷新(压缩)机制,以在长度达到某一值时启动。

编辑:

上面的代码虽然很好delete,但运算符虽然仍然是 O(1),但速度很慢。此外,现代 JS 引擎经过如此优化,对于 <~25000 个项目来说,.shift()无论如何,工作时间复杂度为 O(1)。所以我们需要更好的东西。

在这种特殊情况下,随着发动机的发展,我们必须利用它们的新动力。下面的代码使用了链表,我相信它是截至 2021 年最快、最安全的现代 JS 队列结构。

class Queue {
  #head;
  #last;
  constructor(){
    this.#head;
    this.#last;
  };
  enqueue(value){
    var link = {value, next: void 0};
    this.#last = this.#head ? this.#last.next = link
                            : this.#head      = link;
  }
  dequeue(){
    var first;
    return this.#head && ( first = this.#head.value
                         , this.#head = this.#head.next
                         , first
                         );
  }
  peek(){
    return this.#head && this.#head.value;
  }
};
Run Code Online (Sandbox Code Playgroud)

这是一个非常快的队列结构,并使用私有类字段来隐藏关键变量以防止窥探。