gpt4 book ai didi

javascript - 在 Javascript 中实现优先级队列的有效方法?

转载 作者:可可西里 更新时间:2023-11-01 01:16:57 27 4
gpt4 key购买 nike

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

因此,当向队列中添加新元素时,如果它具有比集合中已有元素更高的优先级值,它就会冒泡到表面。

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

在 Javascript 中如何有效地实现这种优先级队列?

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

执行此操作的好方法是什么?

最佳答案

下面是我认为真正有效的 PriorityQueue 版本,它使用基于数组的二进制堆(其中根位于索引 0,并且索引为 i 的节点的子节点分别位于索引 2i + 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;
}
}
}

示例:

{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%}

关于javascript - 在 Javascript 中实现优先级队列的有效方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42919469/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com