【问题标题】:How does Priority queue compare and store the values during the push operation?优先队列在推送操作期间如何比较和存储值?
【发布时间】:2014-12-30 12:48:53
【问题描述】:

我正在处理优先级队列,我想检查如何使用可比较类比较值。这是我的代码。

#include <iostream>
#include <queue>

using namespace std;

class g {
    public:
        bool operator() (int a, int b) {
        cout<<a<<" "<<b<<endl;
            return (a > b);
        }
};

int main() {
    priority_queue<int,vector<int>,g> p;
    p.push(2);
    cout<<"CHECK1"<<endl;
    p.push(4);
    cout<<"CHECK2"<<endl;
    p.push(8);
    cout<<"CHECK3"<<endl;
    p.push(1);
    cout<<"CHECK4"<<endl;
    while(!p.empty()) {
        cout<<p.top()<<endl;
        p.pop();
    }
}

输出是

CHECK1
2 4
CHECK2
2 8
CHECK3
4 1
2 1
CHECK4
1
8 2
2 4
2
4 8
4
8

我看到当推入 4 时,它与 2 进行比较,当推入 8 时,它再次与 2 进行比较。但是为什么不把 8 和 4 比较呢? 有人可以帮忙吗?

【问题讨论】:

  • 取决于底层数据结构 - 可能是 B-Tree 或 BST

标签: c++ priority-queue


【解决方案1】:

优先级队列通常实现为完美平衡的堆结构。堆可以看作是一棵二叉树,唯一的要求是根的优先级高于(比较器的值较小),即堆条件。

                root
      Lchild1             Rchild1
  Lchild2  Rchild2     Lchild2  empty

任何插入都插入到空白处以保持树的平衡。在插入之后,它会向上移动以保持堆状态。所以在这种情况下,唯一可能的比较是 Rchild1 和 root。

删除/pop() 是通过删除根并在 Lchild2 中交换来完成的,以保持完美平衡,然后将 Lchild2 向下移动以纠正堆条件。

这棵树很容易保存在向量中。

                root(2)
      Lchild1(4)        empty.

8 的插入(在空白处)只需要与根比较即可。

                root(2)
      Lchild1(4)        Rchild1(8).
   empty

在空白处插入1,需要检查4并交换,然后与根比较(和交换)。

有很多可能的内部表示,例如https://gcc.gnu.org/onlinedocs/libstdc++/ext/pb_ds/pq_performance_tests.html。其他包括红黑树。

这也可能有助于Efficiency of the STL priority_queue

【讨论】:

    【解决方案2】:

    std::priority_queue&lt;...&gt; 在内部表示为 d-heap。该表示使用一棵树,其中每个子树的根在该子树中具有最高优先级。它的结构旨在最大限度地减少必要比较的次数。

    当插入一个元素时,它被插入到树的底部,并且只要它具有更高的优先级,就可以沿着到根的路径与父级交换。移除与叶子交换根,移除叶子,然后将根与它所在的子树的最高优先级子树交换,只要它具有较低的优先级。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-07
      • 1970-01-01
      • 2020-10-14
      • 2020-09-07
      • 1970-01-01
      • 2021-06-17
      • 2021-09-19
      相关资源
      最近更新 更多