イテレータ(queue
など)を使用してc ++の標準priority_queue
または標準vector
をトラバースできますか? popを使用したくないのは、キューがデキューされるためです。
助けてくれてありがとう
priority_queue
はすべてのメンバーの反復を許可していません。おそらく、キューの優先順位を無効にするのは簡単すぎるため(トラバースする要素を変更すること)、または「自分の仕事ではない」理由です。
公式の回避策は、代わりにvector
を使用し、make_heap
、Push_heap
、およびpop_heap
で優先度を管理することです。 @Richardの答えでの別の回避策は、priority_queue
から派生したクラスを使用し、protected
可視性を持つ基盤ストレージにアクセスすることです。
このようにできます-バム!少なくともコンテナの単純な繰り返しに関しては、アイテムがキューにある間は必ずしも「ソートされた」順序ではないことに注意してください。
#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;
}
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
がデフォルトで使用されます。どちらの場合も、基礎となるコンテナにアクセスしてそれらを反復処理することはできません。詳細については、 この質問 を参照してください。
はい、priority_queueのコピーを作成し、それを繰り返します。
#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;
}
これは不可能です。別のコンテナを使用する必要があります。おそらく、 deque
が最適です。
あなたの質問につまずいた後に私はこれを見つけました。 std :: priority_queueを継承する実装を記述することにより、これを行う非常に簡単な方法があります。 14行すべてです。
キューはベクターとはまったく異なり、さまざまな目的に使用されます。優先キューは単純に並べ替えられた両端キューであり、バックに直接アクセスすることはできません。ただし、何らかの方法で必死にこれを行いたい場合は、トップ/フロント要素からポップし、リスト/配列/ベクトルに追加してから、要素を(size_t i = 0; i <q.size(); i ++)。私はJavaデータ構造でクラスを取りました。これは試験問題に対する答えでした。さらに、それは私が考えることができる唯一の方法です。
これらの回答の多くは、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のイテレータを指定しないことは、特にそれがor構造のコンテナクラスである場合、まったく意味がないようです。
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_;
};
私自身も同じ質問をしました。優先度キューの基礎となるデータ構造に到達することは非常に困難で、おそらく不可能であることがわかりました。私の場合、これはオブジェクトのベクトルでした。
ただし、標準テンプレートライブラリヒープを使用することになりました。優先度キューとほぼ同じくらい簡単です(プッシュとポップに2つの命令がかかりますが、pqの場合は1) 。
基本的な目的のために、 std::multiset
は同様のプロパティを提供しますが、反復する機能があります。
Less
を定義可能