当前位置: 首页 > 知识库问答 >
问题:

在JavaScript中实现优先级队列的有效方法?

劳和雅
2023-03-14

优先级队列对每个条目都有一个优先级值和数据。

因此,当向队列中添加新元素时,如果该元素的优先级值高于集合中已有的元素,则该元素会浮上表面。

当调用pop时,我们将获得具有最高优先级的元素的数据。

这种优先级队列在JavaScript中的高效实现是什么?

有一个名为PriorityQueue的新对象,创建两个方法(push和pop)来获取两个参数(数据、优先级),这有意义吗?作为一个编码器,这对我来说是有意义的,但是我不确定在底层使用哪种数据结构来允许对元素的排序进行操作。或者我们可以仅仅将它全部存储在一个数组中,每次遍历数组来抓取具有最大优先级的元素吗?

这样做有什么好方法?

共有2个答案

高钱青
2023-03-14

您应该使用标准库,例如闭包库(goog.structs.priorityqueue):

https://google.github.io/closure-library/api/goog.structs.priorityqueue.html

通过单击源代码,您将知道它实际上链接到goog.structs.heap,您可以遵循以下内容:

https://github.com/google/closue-library/blob/master/closule/goog/structs/heap.js

须景辉
2023-03-14

下面是我认为真正有效的priorityqueue版本,它使用基于数组的二进制堆(其中根位于index0,indexI处的节点的子级分别位于index2I+12I+2处)。

此实现包括典型的优先级队列方法,如pushpeekpopsize以及方便方法isemptyreplace(后者是pop的更有效的替代品,后接push)。值不是作为[value,priority]对存储的,而是作为value存储的;这允许对可以使用运算符进行本机比较的类型进行自动优先排序。但是,可以使用传递给priorityqueue构造函数的自定义比较器函数来模拟成对语义的行为,如下例所示。

const top = 0;
const parent = i => ((i + 1) >>> 1) - 1;
const left = i => (i << 1) + 1;
const right = i => (i + 1) << 1;

class PriorityQueue {
  constructor(comparator = (a, b) => a > b) {
    this._heap = [];
    this._comparator = comparator;
  }
  size() {
    return this._heap.length;
  }
  isEmpty() {
    return this.size() == 0;
  }
  peek() {
    return this._heap[top];
  }
  push(...values) {
    values.forEach(value => {
      this._heap.push(value);
      this._siftUp();
    });
    return this.size();
  }
  pop() {
    const poppedValue = this.peek();
    const bottom = this.size() - 1;
    if (bottom > top) {
      this._swap(top, bottom);
    }
    this._heap.pop();
    this._siftDown();
    return poppedValue;
  }
  replace(value) {
    const replacedValue = this.peek();
    this._heap[top] = value;
    this._siftDown();
    return replacedValue;
  }
  _greater(i, j) {
    return this._comparator(this._heap[i], this._heap[j]);
  }
  _swap(i, j) {
    [this._heap[i], this._heap[j]] = [this._heap[j], this._heap[i]];
  }
  _siftUp() {
    let node = this.size() - 1;
    while (node > top && this._greater(node, parent(node))) {
      this._swap(node, parent(node));
      node = parent(node);
    }
  }
  _siftDown() {
    let node = top;
    while (
      (left(node) < this.size() && this._greater(left(node), node)) ||
      (right(node) < this.size() && this._greater(right(node), node))
    ) {
      let maxChild = (right(node) < this.size() && this._greater(right(node), left(node))) ? right(node) : left(node);
      this._swap(node, maxChild);
      node = maxChild;
    }
  }
}

null

{const top=0,parent=c=>(c+1>>>1)-1,left=c=>(c<<1)+1,right=c=>c+1<<1;class PriorityQueue{constructor(c=(d,e)=>d>e){this._heap=[],this._comparator=c}size(){return this._heap.length}isEmpty(){return 0==this.size()}peek(){return this._heap[top]}push(...c){return c.forEach(d=>{this._heap.push(d),this._siftUp()}),this.size()}pop(){const c=this.peek(),d=this.size()-1;return d>top&&this._swap(top,d),this._heap.pop(),this._siftDown(),c}replace(c){const d=this.peek();return this._heap[top]=c,this._siftDown(),d}_greater(c,d){return this._comparator(this._heap[c],this._heap[d])}_swap(c,d){[this._heap[c],this._heap[d]]=[this._heap[d],this._heap[c]]}_siftUp(){for(let c=this.size()-1;c>top&&this._greater(c,parent(c));)this._swap(c,parent(c)),c=parent(c)}_siftDown(){for(let d,c=top;left(c)<this.size()&&this._greater(left(c),c)||right(c)<this.size()&&this._greater(right(c),c);)d=right(c)<this.size()&&this._greater(right(c),left(c))?right(c):left(c),this._swap(c,d),c=d}}window.PriorityQueue=PriorityQueue}

// Default comparison semantics
const queue = new PriorityQueue();
queue.push(10, 20, 30, 40, 50);
console.log('Top:', queue.peek()); //=> 50
console.log('Size:', queue.size()); //=> 5
console.log('Contents:');
while (!queue.isEmpty()) {
  console.log(queue.pop()); //=> 40, 30, 20, 10
}

// Pairwise comparison semantics
const pairwiseQueue = new PriorityQueue((a, b) => a[1] > b[1]);
pairwiseQueue.push(['low', 0], ['medium', 5], ['high', 10]);
console.log('\nContents:');
while (!pairwiseQueue.isEmpty()) {
  console.log(pairwiseQueue.pop()[0]); //=> 'high', 'medium', 'low'
}
.as-console-wrapper{min-height:100%}
 类似资料:
  • 我正在编写一个涉及堆实现的代码,在我的bubbleUp方法中,在我的while循环行中,我似乎遇到了一个取消引用的错误。这可能是一个相当基本的问题,但解决这个问题的最佳方法是什么?我在实现removeHigh方法时也遇到了一些问题,该方法旨在从队列中移除最高的元素。

  • 问题 怎样实现一个按优先级排序的队列? 并且在这个队列上面每次 pop 操作总是返回优先级最高的那个元素 解决方案 下面的类利用 heapq 模块实现了一个简单的优先级队列: import heapq class PriorityQueue: def __init__(self): self._queue = [] self._index = 0

  • 在谷歌搜索了几天之后,我相信我完全迷路了。我想实现一种优先级队列,它大约有3个队列: 高优先级队列(每日),需要先处理 中等优先级队列(每周),如果队列#1中没有项目,将进行处理。(此队列中的ok消息根本不处理) 低优先级队列(每月),如果队列#1中没有项目,将进行处理 最初,我有以下流程,让消费者使用所有三个队列中的消息,并检查队列#1、#2和#3中是否有任何项目。然后我意识到这是错误的,因为:

  • 我需要一个优先级队列,它首先获得具有最高优先级值的项目。我当前正在使用队列库中的PriorityQueue类。但是,这个函数只先返回值最小的项。我尝试了一些很难看的解决方案,比如(sys.maxint-priority)作为优先级,但我只是想知道是否存在更优雅的解决方案。

  • 我试图实现Dijkstra算法的一个版本,以找到公共汽车从起点到终点的最短路线。不幸的是,我似乎找不到swift提供优先级队列类型的库或其他方式,所以我似乎必须自己编写代码。 话虽如此,有人能指出我做这件事的正确方向吗? 目前我的想法如下: 到目前为止这是我的代码。似乎太短太残忍了...我一定是在概念上漏掉了什么。

  • 本文向大家介绍Python实现优先级队列结构的方法详解,包括了Python实现优先级队列结构的方法详解的使用技巧和注意事项,需要的朋友参考一下 最简单的实现 一个队列至少满足2个方法,put和get. 借助最小堆来实现. 这里按"值越大优先级越高"的顺序.  使用heapq模块来实现 下面的类利用 heapq 模块实现了一个简单的优先级队列: 下面是它的使用方式: 仔细观察可以发现,第一个 pop