【问题标题】:How can I create Min stl priority_queue?如何创建 Min stl priority_queue?
【发布时间】:2011-01-27 05:05:51
【问题描述】:

默认的 stl 优先级队列是 Max one(Top 函数返回最大的元素)。

为简单起见,说它是 int 值的优先级队列。

【问题讨论】:

    标签: c++ stl priority-queue


    【解决方案1】:

    使用std::greater作为比较函数:

    std::priority_queue<int, std::vector<int>, std::greater<int> > my_min_heap;
    

    【讨论】:

    • @eriks 你有一些选择。要么你的班级定义了operator&gt;,这对std::greater 来说就像魅力一样。如果您愿意,您也可以编写自己的函子,而不是 std::greater
    • @AraK,我想你的意思是operator&lt; ;)
    • 为什么我们必须添加向量 ?这不是很明显,正如我们已经说过我们想要 int 吗?第二个参数还有哪些其他选项?
    • @CarryonSmiling 在标准模板库中,vectordeque 类满足底层容器必须满足的优先级队列要求。您还可以使用自定义容器类。您可以在cplusplus.com/reference/queue/priority_queue 上找到更详细的解释
    • 有人能解释一下为什么最小堆使用更大而不是更少吗?
    【解决方案2】:

    一种方法是定义一个合适的比较器来操作普通优先级队列,这样它的优先级就会被颠倒:

     #include <iostream>  
     #include <queue>  
     using namespace std;  
    
     struct compare  
     {  
       bool operator()(const int& l, const int& r)  
       {  
           return l > r;  
       }  
     };  
    
     int main()  
     {  
         priority_queue<int,vector<int>, compare > pq;  
    
         pq.push(3);  
         pq.push(5);  
         pq.push(1);  
         pq.push(8);  
         while ( !pq.empty() )  
         {  
             cout << pq.top() << endl;  
             pq.pop();  
         }  
         cin.get();  
     }
    

    分别输出 1、3、5、8。

    通过 STL 和 Sedgewick's implementations 使用优先级队列的一些示例在 here 中给出。

    【讨论】:

    • 您能否解释一下为什么我们使用 l>r 而不是 l
    • 优先级队列的默认比较器是 lconstructor default parameter 中看到这一点。通过执行 l>r 或 r
    • @AndyUK 你好,¿你为什么使用结构来实现比较运算符?提前致谢
    • C++ 中的默认优先级队列是最大优先级队列。
    • @DhruvMullick 正如 qwr 所说,默认情况下,PQ 是最大优先级队列,使用的比较器是 less,因此为了获得最小 PQ,您需要使用更大 或 l 来反转它>r.
    【解决方案3】:

    priority_queue 的第三个模板参数是比较器。将其设置为使用greater

    例如

    std::priority_queue<int, std::vector<int>, std::greater<int> > max_queue;
    

    #include &lt;functional&gt; 需要 std::greater

    【讨论】:

    • @Potatoswatter:情况并非总是如此。
    • 这比接受的答案更好,因为它还提到了#include
    【解决方案4】:

    您可以通过多种方式做到这一点:
    1.使用greater作为比较函数:

     #include <bits/stdc++.h>
    
    using namespace std;
    
    int main()
    {
        priority_queue<int,vector<int>,greater<int> >pq;
        pq.push(1);
        pq.push(2);
        pq.push(3);
    
        while(!pq.empty())
        {
            int r = pq.top();
            pq.pop();
            cout<<r<< " ";
        }
        return 0;
    }
    

    2。通过更改符号来插入值(使用减号 (-) 表示正数,使用加号 (+) 表示负数:

    int main()
    {
        priority_queue<int>pq2;
        pq2.push(-1); //for +1
        pq2.push(-2); //for +2
        pq2.push(-3); //for +3
        pq2.push(4);  //for -4
    
        while(!pq2.empty())
        {
            int r = pq2.top();
            pq2.pop();
            cout<<-r<<" ";
        }
    
        return 0;
    }
    

    3。使用自定义结构或类:

    struct compare
    {
        bool operator()(const int & a, const int & b)
        {
            return a>b;
        }
    };
    
    int main()
    {
    
        priority_queue<int,vector<int>,compare> pq;
        pq.push(1);
        pq.push(2);
        pq.push(3);
    
        while(!pq.empty())
        {
            int r = pq.top();
            pq.pop();
            cout<<r<<" ";
        }
    
        return 0;
    }
    

    4。使用自定义结构或类,您可以按任何顺序使用 priority_queue。 假设,我们想根据薪水降序排列人,如果平,则根据他们的年龄。

        struct people
        {
            int age,salary;
    
        };
        struct compare{
        bool operator()(const people & a, const people & b)
            {
                if(a.salary==b.salary)
                {
                    return a.age>b.age;
                }
                else
                {
                    return a.salary>b.salary;
                }
    
        }
        };
        int main()
        {
    
            priority_queue<people,vector<people>,compare> pq;
            people person1,person2,person3;
            person1.salary=100;
            person1.age = 50;
            person2.salary=80;
            person2.age = 40;
            person3.salary = 100;
            person3.age=40;
    
    
            pq.push(person1);
            pq.push(person2);
            pq.push(person3);
    
            while(!pq.empty())
            {
                people r = pq.top();
                pq.pop();
                cout<<r.salary<<" "<<r.age<<endl;
        }
    
    1. 运算符重载也可以得到同样的结果:

      struct people
      {
      int age,salary;
      
      bool operator< (const people & p)const
      {
          if(salary==p.salary)
          {
              return age>p.age;
          }
          else
          {
              return salary>p.salary;
          }
      }};
      

      在主函数中:

      priority_queue<people> pq;
      people person1,person2,person3;
      person1.salary=100;
      person1.age = 50;
      person2.salary=80;
      person2.age = 40;
      person3.salary = 100;
      person3.age=40;
      
      
      pq.push(person1);
      pq.push(person2);
      pq.push(person3);
      
      while(!pq.empty())
      {
          people r = pq.top();
          pq.pop();
          cout<<r.salary<<" "<<r.age<<endl;
      }
      

    【讨论】:

    • 你不是说bool operator &gt; (const people &amp; p)const in 5) 运算符重载
    • 其实你说得对,5) 确实有效,只是奇怪,我从没见过&lt; 这么重载,最好是重载&gt; 并使用greater&lt;people&gt;
    【解决方案5】:

    在 C++11 中,您还可以为方便创建别名:

    template<class T> using min_heap = priority_queue<T, std::vector<T>, std::greater<T>>;
    

    并像这样使用它:

    min_heap<int> my_heap;
    

    【讨论】:

      【解决方案6】:

      解决这个问题的一种方法是,将priority_queue中每个元素的负数推入priority_queue中,这样最大的元素将成为最小的元素。在进行pop操作时,对每个元素取反。

      #include<bits/stdc++.h>
      using namespace std;
      
      int main(){
          priority_queue<int> pq;
          int i;
      
      // push the negative of each element in priority_queue, so the largest number will become the smallest number
      
          for (int i = 0; i < 5; i++)
          {
              cin>>j;
              pq.push(j*-1);
          }
      
          for (int i = 0; i < 5; i++)
          {
              cout<<(-1)*pq.top()<<endl;
              pq.pop();
          }
      }
      

      【讨论】:

        【解决方案7】:

        基于以上所有答案,我创建了一个关于如何创建优先级队列的示例代码。 注意:它适用于 C++11 及以上编译器

        #include <iostream>
        #include <vector>
        #include <iomanip>
        #include <queue>
        
        using namespace std;
        
        // template for prirority Q
        template<class T> using min_heap = priority_queue<T, std::vector<T>, std::greater<T>>;
        template<class T> using max_heap = priority_queue<T, std::vector<T>>;
        
        const int RANGE = 1000;
        
        vector<int> get_sample_data(int size);
        
        int main(){
          int n;
          cout << "Enter number of elements N = " ; cin >> n;
          vector<int> dataset = get_sample_data(n);
        
          max_heap<int> max_pq;
          min_heap<int> min_pq;
        
          // Push data to Priority Queue
          for(int i: dataset){
            max_pq.push(i);
            min_pq.push(i);
          }
        
          while(!max_pq.empty() && !min_pq.empty()){
            cout << setw(10) << min_pq.top()<< " | " << max_pq.top() << endl;
            min_pq.pop();
            max_pq.pop();
          }
        
        }
        
        
        vector<int> get_sample_data(int size){
          srand(time(NULL));
          vector<int> dataset;
          for(int i=0; i<size; i++){
            dataset.push_back(rand()%RANGE);
          }
          return dataset;
        }
        

        以上代码的输出

        Enter number of elements N = 4
        
                33 | 535
                49 | 411
               411 | 49
               535 | 33
        

        【讨论】:

          【解决方案8】:

          我们可以通过多种方式做到这一点。

          使用模板比较器参数

              int main() 
              {
                priority_queue<int, vector<int>, greater<int> > pq;
          
                pq.push(40);
                pq.push(320);
                pq.push(42);
                pq.push(65);
                pq.push(12);
          
                cout<<pq.top()<<endl;
                return 0;
              }
          

          使用已定义的比较器类

               struct comp
               {
                  bool operator () (int lhs, int rhs)
                  {
                     return lhs > rhs;
                  }
               };
          
              int main()
              {
                 priority_queue<int, vector<int>, comp> pq;
          
                 pq.push(40);
                 pq.push(320);
                 pq.push(42);
                 pq.push(65);
                 pq.push(12);
          
                 cout<<pq.top()<<endl;
          
                 return 0;
              }
          

          【讨论】:

            【解决方案9】:

            将值与-1相乘,使用最大堆得到最小堆的效果

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-02-27
              • 1970-01-01
              • 2022-08-03
              • 1970-01-01
              • 2021-09-26
              • 1970-01-01
              相关资源
              最近更新 更多