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

2023-12-02

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

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

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

在 Javascript 中,这种优先级队列的有效实现是什么?

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

有什么好的方法可以做到这一点?


下面是我认为真正有效的版本PriorityQueue它使用基于数组的二进制堆(其中根位于索引处)0,以及索引处节点的子节点i处于指数2i + 1 and 2i + 2, 分别)。

该实现包括经典的优先级队列方法,例如push, peek, pop, and size,以及便捷的方法isEmpty and replace(后者是更有效的替代品pop紧接着是push)。值的存储方式不是[value, priority]成对,但简单地作为values;这允许对可以使用本机比较的类型进行自动优先级排序>操作员。传递给的自定义比较器函数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;
    }
  }
}

Example:

{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%}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在Javascript中实现优先级队列的有效方法? 的相关文章

随机推荐

  • 使用 updateDate() 方法设置 DatePicker 的日期

    我目前正在制作日期 时间选择器课程 本质上 我创建了 3 个单选按钮 明天 两天内 和 下周 我想要做的是让这些单选按钮自动将日期选择器设置为提前相应的天数 提前 1 2 和 7 天 当用户单击单选按钮时 我尝试使用 updateDate
  • Google 搜索检索搜索关键字的结果数量

    我有一个关键字列表 想知道每个关键字的谷歌搜索结果数量 对于我的研究项目 我正在使用下面的代码来实现相同的目的 def showsome searchfor hits 1 try query urllib urlencode q searc
  • $_SERVER['REMOTE_ADDR'] 的问题

    我使用 SERVER REMOTE ADDR 它返回客户端 ip 地址 用户查看当前页面的 IP 地址 但现在 和相同的代码 它返回主机 ip 地址 我用 ip 位置检查了 ip 地址 问题是主机还是什么 感谢你 您应该查询HTTP X F
  • 体积的imfilter速度

    我正在研究一种算法 该算法需要过滤 3D 矩阵 非稀疏 512 3 来查找边缘 我只想找到每个切片中的边缘 所以我一直在执行以下操作 2D loop appaoch x y ndgrid floor 3 sigma ceil 3 sigma
  • APK 签名错误:无法从密钥库读取密钥

    我正在 intellij 和 gradle 下开发 Android 应用程序 并使用以下方式生成密钥库文件 keytool genkey v keystore my release key keystore alias alias name
  • 是什么意思[重复]

    这个问题在这里已经有答案了 这是代码 def my func f arg return f arg print lambda x 2 x x 5 gt gt gt
  • 控制笔记本相关表达式的 Rasterize[] 宽度

    Update向导先生的答案给出了像素完美的结果 但它仅适用于 Windows 并且会破坏剪贴板内容 我的答案应该适用于任何平台 但不太精确 例如它省略了输入 输出标签 但它确实允许设置光栅化宽度 这个问题我当时就出现了尝试为图像上传器制作预
  • WebStorm:如何美化 JavaScript 文件中引号中的 HTML

    我的中有以下块app component ts file Component selector my app template h1 title h1 h2 My Heroes h2 ul class heroes li li ul h2
  • 打开目录对话框

    我希望用户选择一个目录 用于保存我将生成的文件 我知道在 WPF 中我应该使用OpenFileDialog来自 Win32 但不幸的是 该对话框需要选择文件 如果我只是单击 确定 而不选择文件 它就会保持打开状态 我可以通过让用户选择一个文
  • 通过代码模拟触摸控制

    我正在尝试使用头部手势来浏览我的 Google Glass 应用程序 我能够识别头部姿势 例如向右看 向左看和向上看 他们每个人都有自己的方法来识别该手势时该怎么做 现在我需要在每个方法中模拟相应的触摸手势 所以它会认为我正在向左或向右滑动
  • C#:更改按钮背景颜色没有效果

    我在 Windows 窗体中使用 C 按钮时遇到问题 我以编程方式创建了许多按钮 然后将它们添加到表单中 有趣的是 除了修改按钮之外 对这些按钮 位置和大小 的每次修改BackColor很容易被执行 只有按钮的颜色保持不变 代码看起来像这样
  • Flash AS3 - 如何设置高质量录音

    目前 我正在使用 mic rate 100 这仅提供 63kbps Flash AS3 是否可以将比特率设置为高于 63kbps From the docs 可接受的值为 5 8 11 22 和 44 所以输入其中之一 根据文档 它的测量单
  • 如果没有父窗口,则无法在 PyQt 中创建新窗口

    我开始使用 PyQt 在 Python 中编写一个简单的文本编辑器 然后遇到了这个问题 对于 新文档 按钮 我想打开一个新的空文本编辑器 无论第一个窗口发生什么情况 它都会保持打开状态 问题是我让它显示窗口的唯一方法是发送self作为参数
  • 在经典的asp中读取csv文件。问题:列值被截断最多 300 个字符

    我有一个页面可以上传 csv 文件并保存到数据库中的表中 我正在使用下面的连接字符串来读取 csv 文件 set connection Server CreateObject ADODB Connection connection Open
  • 计算向量中零和一的百分比?

    我已经使用以下代码获得了矢量以及零和一的数量 u 1 1 1 1 1 0 0 0 1 1 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 transitions find u u 2 end u end 1 value u tr
  • Windows Phone 7 - 来电屏幕

    有没有办法在接到电话时将数据添加到来电屏幕 如果可能的话 我希望能够向该屏幕添加文本 Update 如果当前无法向该屏幕添加文本 是否有办法根据来电触发代码 您可以执行与来电相关的任何操作的唯一方法是通过 Obscured 事件得知此情况已
  • iOS 7 iPad Safari 横向innerHeight/outerHeight 布局问题

    我们发现 iOS 7 中 Safari 上高度为 100 的 Web 应用程序存在问题 似乎 window innerHeight 672px 与 window outerHeight 692px 不匹配 但仅限于横向模式 最终发生的情况是
  • filepicker.io Javascript API 调用导致不安全的 javascript 错误

    我目前正在使用 AngularJS 我想从我的上传控制器调用 filePicker pickAndStore 对 filepicker io API 函数的任何调用都会导致 不安全的 Javascript 尝试 错误 请求访问的帧具有 ht
  • SecurityError:操作不安全。使用 Htmlcanvas [重复]

    这个问题在这里已经有答案了 尝试转换图像我drag并将我的画布元素放入 PNG 或 Jpeg 照片中 有点类似于 Polyvore 的情绪板概念 这样我就可以在一张 PNG 或 Jpeg 照片中一次性查看放置在画布上的所有图像 这样我就可以
  • 在Javascript中实现优先级队列的有效方法?

    优先级队列对于每个条目都有一个优先级值和数据 因此 当向队列添加新元素时 如果它具有比集合中已有元素更高的优先级值 它就会冒泡到表面 当调用 pop 时 我们会获取具有最高优先级的元素的数据 在 Javascript 中 这种优先级队列的有