如何迭代priority_queue?

时间:2010-12-19 19:50:36

标签: c++ stl queue

我可以使用迭代器(如priority_queue)在c ++中遍历标准queue或标准vector吗?我不想使用pop,因为它导致我的队列出列。

感谢您的帮助

15 个答案:

答案 0 :(得分:16)

priority_queue不允许迭代所有成员,大概是因为它会使队列的优先级排序无效(通过修改你遍历的元素)或者它可能是“不是我的工作”理。

官方解决方法是改为使用vector并使用make_heappush_heappop_heap自行管理优先级。在@ Richard的回答中,另一个解决方法是使用从priority_queue派生的类,并访问具有protected可见性的底层存储。

答案 1 :(得分:12)

你可以这样做 - bam!请注意,项目在队列中时不一定按“排序”顺序排列,至少在容器的直接迭代方面是这样。

#include <queue>
#include <cstdlib>
#include <iostream>
using namespace std;

template <class T, class S, class C>
S& Container(priority_queue<T, S, C>& q) {
    struct HackedQueue : private priority_queue<T, S, C> {
        static S& Container(priority_queue<T, S, C>& q) {
            return q.*&HackedQueue::c;
        }
    };
    return HackedQueue::Container(q);
}

int main()
{
    priority_queue<int> pq;
    vector<int> &tasks = Container(pq);

    cout<<"Putting numbers into the queue"<<endl;
    for(int i=0;i<20;i++){
        int temp=rand();
        cout<<temp<<endl;
        pq.push(temp);
    }

    cout<<endl<<"Reading numbers in the queue"<<endl;
    for(vector<int>::iterator i=tasks.begin();i!=tasks.end();i++)
        cout<<*i<<endl;

    cout<<endl<<"Taking numbers out of the queue"<<endl;
    while(!pq.empty()){
        int temp=pq.top();
        pq.pop();
        cout<<temp<<endl;
    }

    return 0;
}

答案 2 :(得分:11)

queue有目的地提供有限的接口,排除迭代。但由于queue使用deque作为基础容器,为什么不直接使用deque

#include <iostream>
#include <queue>
using namespace std;

int main() {
  deque<int> q;
  q.push_back(1);
  q.push_back(2);
  q.push_back(3);
  for(deque<int>::iterator it = q.begin(); it != q.end(); ++it)
    cout << *it << endl;
}

优先级队列的类似答案:不,你不能。但在这种情况下,默认使用vector。在任何情况下,您都无法访问底层容器来迭代它们。有关详细信息,请参阅this question

答案 3 :(得分:4)

是的,制作priority_queue的副本并对其进行迭代。

答案 4 :(得分:3)

这是不可能的。您必须使用不同的容器,可能deque最适合您。

答案 5 :(得分:3)

我在遇到你的问题后发现了这一点。通过编写继承自std :: priority_queue的实现,有一种非常简单的方法。全部是14行。

http://www.linuxtopia.org/online_books/programming_books/c++_practical_programming/c++_practical_programming_189.html

答案 6 :(得分:2)

队列与矢量完全不同,用于不同目的。优先级队列只是排序的deques,没有直接访问后面。但是,如果您迫切希望以任何方法执行此操作,您可以执行的操作是从顶部/前部元素弹出,将其添加到列表/数组/向量,然后将元素推回到队列中(size_t i = 0; i&lt; q.size(); i ++)。我参加了java数据结构课程,这是考试问题的答案。另外,这是我能想到的唯一方法。

答案 7 :(得分:2)

#include <queue>
#include <iostream>

int main() {
    std::priority_queue<int> pq;

    pq.push_back(1);
    pq.push_back(2);
    pq.push_back(3);

    std::priority_queue<int> temp = pq;

    while (!temp.empty()) {
        std::cout << temp.top() << std::endl;
        temp.pop();
    }

    return 0;
}

答案 8 :(得分:1)

这些答案中的许多都依赖于编码/使用许多C ++神秘功能。这没关系,有趣并且资助昂贵的程序员。一个快速,便宜的程序但运行成本更高的直接解决方案是:

// 
// Only use this routine when developing code, NOT for production use!!
//
// Note. _pq is in private for a class that uses the priority queue
// and listQueue is a public method in that same class.
//
void listQueue() {

    // allocate pointer to a NEW container
    priority_queue<int>* new_pq = new  priority_queue<int>;

    while (!_pq->empty()) {

        int el = _pq->top();

        cout << "(" << el << ")" << endl;

        new_pq->push(el);

        _pq->pop();

    } // end while;

    // remove container storage
    delete(_pq);

    // viola, new container same as the old
    _pq = new_pq;

} // end of listQueue;

顺便说一句,不为priority_queue提供迭代器似乎是完全不明智的,特别是当它是一个或结构的容器类时。

答案 9 :(得分:1)

How I can find value in priority queue? 差不多一样。容器受保护,请使用此技巧进行访问。

c ++版本> = 11

#include<iostream>
#include<queue>
using namespace std;
template<class T, class C = vector<T>, class P = less<typename C::value_type> >
struct heapq :std::priority_queue<T,C,P> {
    using priority_queue<T,C,P>::priority_queue;
    typename C::iterator begin() { return std::priority_queue<T, C, P>::c.begin(); }
    typename C::iterator end() { return std::priority_queue<T, C, P>::c.end(); }
};
int main(){
    heapq<int> q;
    q.push(100);
    q.push(80);
    q.push(60);
    for(auto e:q) cout<<e<<endl;
}

答案 10 :(得分:0)

我自己也有同样的问题。我发现要到达优先级队列下的数据结构是非常困难的,也许是不可能的。在我的例子中,这是一个对象的矢量。

但是,我最终使用了标准模板库堆。它几乎和优先级队列一样容易(它需要两个指令来推送和弹出,而pq则为1),否则行为似乎是相同的 和 如果我不修改它,我可以获得基础数据结构。

答案 11 :(得分:0)

C ++ priority_queue不提供.begin()指针(就像vector会做的那样),你可以使用它来迭代它。

如果要遍历优先级队列以搜索它是否包含值,则可以创建包装器优先级队列并使用哈希集来跟踪队列中的内容。

class MyPriorityQueue {

   MyPriorityQueue() {}

   void push(int item) {
     if (!contains(item)){
       pq_.push(item);
       set_.emplace(item);
     }
   }
   void pop() {
     if (!empty()) {
       int top = pq_.top();
       set_.erase(top);
       pq_.pop();
     }
   }
   int top() { return pq_.top(); }
   bool contains(int item) { return set_.find(item) != set_.end(); }
   bool empty() const { return set_.empty(); }

 private:
   std::priority_queue<int> pq_;
   std::unordered_set<int> set_;
};

答案 12 :(得分:0)

出于基本目的,std::multiset将为您提供类似的属性,但具有迭代功能:

  • 可以定义已排序的项目,自定义Less
  • 密钥可以多次出现
  • 快速访问并删除第一项

答案 13 :(得分:0)

如果要以有序的方式(复杂度(logN))推送项目。但也想按递增顺序遍历元素,可以使用set<int>。 集通常以二进制搜索树的形式实现。

集合是可迭代的(开始,结束,rbegin,rend等)

答案 14 :(得分:-1)

我遇到了同样的问题,我希望迭代优先级队列而不会出列(因此会破坏我的队列)。我通过将priority_queue指针重新指向指向向量的指针(因为我的priority_queue使用向量作为其容器)使我的工作成为可能。这是它的样子:

class PriorityQueue {
  private:
    class Element {
    int x; 
    //Other fields
    ...
    ..
    //Comparator function
    bool operator()(const Element* e1, const Element* e2) const {
        // Smallest deadline value has highest priority.
        return e1->x > e2->x;
    }
    };
    // Lock to make sure no other thread/function is modifying the queue
    // Ofcourse we can do our operation w/o lock. if we are sure what is happening in other functions
    pthread_mutex_t lock;   
    std::priority_queue<Element*, std::vector<Element*>, Element> pq;

  public:
    PriorityQueue();
    ~PriorityQueue();
    //print the all the elements of the queue
    void print_queue_elements() {
        std::vector<PriorityQueue::Element*> *queue_vector;
        //Acquire the lock
        pthread_mutex_lock(&lock);
        //recast the priority queue to vector
        queue_vector = reinterpret_cast<std::vector<PriorityQueue::Element*> *>(&pq);
        for(std::vector<PriorityQueue::Element*>::iterator it = (*queue_vector).begin(); it != (*queue_vector).end(); it++) {
            //Assuming Element class has string function
            printf("My Element %s", (*it)->string);
            //other processing with queue elements
        }
        //Release the lock
        pthread_mutex_unlock(&lock);    

    }
    //other functions possibly modifying the priority queue
    ...
    ..
    .
 };

现在我使用reinterpret_cast,人们可以争论类型安全。但在这种情况下,我确信所有其他函数访问/更改队列(所有这些都是安全的)..我觉得这比将整个队列的内容复制到其他容器要好得多。

我实际上期待static_cast工作..因为priority_queue是容器上的适配器(在我们的例子中是vector),但它没有,我不得不使用reinterpret_cast