質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

2415閲覧

priority_queueの各要素を表示する方法、またはpush()時に再ソートされるかどうか知りたい

ratera

総合スコア54

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2020/07/07 06:52

編集2020/07/07 06:58

事象

VScodeのデバッガを利用して、priority_queueに対してpush()したときに、ソートされる場合とされない場合があります。

■更新されない場合(13行目のステートメントのpushで更新)
イメージ説明

■更新される場合(15行目のステートメントのpushで更新)

イメージ説明

質問事項

  • priority_queueはクラスとは違うため、どのように要素を出力したらよいのか教えてほしい。

//for (int i = 0;i < Q.size();i++) printf("%d des",Q[i]);だとエラーに当然なりました。

  • priority_queueのソートタイミングがいつなのか知りたいが、(デバッガでも確認できず、)知りたい。

#### コード

C++

1#include <iostream> 2#include <queue> 3#include <vector> 4#include <functional> 5using namespace std; 6 7int main() { 8 // 例 1: Q に色々な操作を行う(x1 = 116, x2 = 110, x3 = 122, x4 = 2 となります) 9 priority_queue<int, vector<int>, greater<int>> Q; 10 Q.push(116); // この時点で、小さい順に {116} 11 //for (int i = 0;i < Q.size();i++) printf("%d des",Q[i]); 12 Q.push(145); // この時点で、小さい順に {116, 145} 13 Q.push(122); // この時点で、小さい順に {116, 122, 145} 14 int x1 = Q.top(); 15 Q.push(110); // この時点で、小さい順に {110, 116, 122, 145} 16 int x2 = Q.top(); 17 Q.pop(); // この時点で、小さい順に {116, 122, 145} 18 Q.pop(); // この時点で、小さい順に {122, 145} 19 int x3 = Q.top(); 20 int x4 = Q.size(); 21 22 cout << x1 << " " << x2 << " " << x3 << " " << x4 << endl; 23 return 0; 24}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

priority_queue のハラワタを晒す方法:

C++

1#include <iostream> 2#include <queue> 3#include <vector> 4#include <functional> 5using namespace std; 6 7template <class _Ty, class _Container = vector<_Ty>, class _Pr = less<typename _Container::value_type>> 8class my_priority_queue : public std::priority_queue<_Ty, _Container, _Pr> { 9public: 10 const _Container& guts() const { 11 return this->c; // コレがハラワタ。protectedメンバなので導出クラスなら晒せる。 12 } 13}; 14 15// ハラワタをプリントする 16template<typename C> 17void print(const C& cont) { 18 for ( const auto& item : cont ) { 19 std::cout << item << ' '; 20 } 21 std::cout << std::endl; 22} 23 24int main() { 25 // 例 1: Q に色々な操作を行う(x1 = 116, x2 = 110, x3 = 122, x4 = 2 となります) 26 my_priority_queue<int, vector<int>, greater<int>> Q; 27 Q.push(116); // この時点で、小さい順に {116} 28 print(Q.guts()); 29 Q.push(145); // この時点で、小さい順に {116, 145} 30 Q.push(122); // この時点で、小さい順に {116, 122, 145} 31 int x1 = Q.top(); 32 Q.push(110); // この時点で、小さい順に {110, 116, 122, 145} 33 int x2 = Q.top(); 34 print(Q.guts()); 35 Q.pop(); // この時点で、小さい順に {116, 122, 145} 36 Q.pop(); // この時点で、小さい順に {122, 145} 37 int x3 = Q.top(); 38 int x4 = Q.size(); 39 cout << "---------------\n"; 40 cout << x1 << " " << x2 << " " << x3 << " " << x4 << endl; 41 return 0; 42}

[追記]

priority_queueのソートタイミングがいつなのか知りたいが、(デバッガでも確認できず、)知りたい。

多くのpriority_queue実装は、
実は真面目にソートせずヒープで済ませることで処理時間を抑えています。

ひとつづつ取り出すことしかできないので、
「その時点でいちばん大きい(小さい)ひとつだけが特定できればいい」
ちゅーわけで、真面目にソートせんでもえぇのです。

投稿2020/07/07 07:53

編集2020/07/07 11:44
episteme

総合スコア16612

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ratera

2020/07/07 09:41

なるほどおおおおおおです。 ヒープだから、ソートされてたりされてなかったりするんだ。 裏っかわの事情に考えを至らせることも大事ですね!勉強になります!ありがとうございます! (ハラワタを出せるぷよぐらみんぐが早くできるようになりたい。。。どのくらいの経験を積めばいけるのか今のところさっぱりですががが!)
episteme

2020/07/07 09:52

少なくとも priority_queue に関する限り、ヘッダ読めばその実装バレバレです。 ちーとキツいが眺めてみる価値はありますぜ。
ratera

2020/07/07 10:03 編集

へへ、これは良いことききやした。 なんやかんや初めてQ.push()の定義にお邪魔してみたところ、push_heapってめっちゃ書いてあったー。 その先は神々のおわす世界でしたが( ;∀;)、とりあえずどんなアルゴリズムが使われているかだけなら簡単にわかる!すごい!感謝です!
episteme

2020/07/07 10:48

そのかわり、priorityの等しい複数の要素がpushされた場合、その順序は不定となります。
ratera

2020/07/07 11:58 編集

微修正ありがとうございます。 一番大きいもの(ツリー状の根に当たる部分)の順序のみ担保されていて、 それ以外については不定の場合があるという理解をしました! まずは、ヒープソートを実際に手を動かしてならべ直したら、怪しい箇所をきちんと理解できる気がします。 たぶん木構造の深さが同じ個所は、順序は怪しそうな気がしています! (int以外の比較できないものの話をされているのかもしれませんが、こちらはまた後日ぶちあたってから考えることにします。)
guest

0

[余計なお世話]

priorityの等しい複数の要素がpushされた場合、その順序は不定となります。

の解説。

たとえば int値の 一の位を優先度として priority_queue を使うと:

C++

1#include <iostream> 2#include <queue> 3 4struct priority_compare { 5 bool operator()(int x, int y) const { 6 return x % 10 < y % 10; 7 } 8}; 9 10int main() { 11 std::priority_queue<int,std::vector<int>,priority_compare> Q; 12 13 // 10, 11, 12, ... 49 を Qに投げ込む 14 for ( int i = 10; i < 50; ++i ) Q.push(i); 15 16 // 優先度の高いものから取り出す 17 while ( !Q.empty() ) { 18 std::cout << Q.top() << ' '; 19 Q.pop(); 20 } 21}

期待する結果は 19, 29, 39, 49, 18, 28, ... なのですが
実際は:

19 39 29 49 38 18 28 48 37 17 47 27 36 16 46 26 45 15 35 25 24 14 44 34 33 43 13 23 22 32 12 42 41 21 31 11 10 40 20 30

優先度が等しい複数の要素がpush()した順に取り出されることはないんですわー

投稿2020/07/08 22:08

編集2020/07/09 00:14
episteme

総合スコア16612

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ratera

2020/07/09 04:24

わーい、ありがとうございます!。 実際のところ、優先度順とはなんぞや?となっていました。 greater<int>などの場合は数の大きさなのであまり意識しなくてよかったので。 今回だと優先度と数値を持ったqueueがいくつもあって、まさに優先度がかぶるケースという話ですね! 別口の質問になりますが、priority_queueの[containerの概念](https://programming-place.net/ppp/contents/cpp/library/012.html )や、頂いた以下の構造体の読み方など、文法入門書から外れるものは1時間くらい調べても理解にいたりません。 手持ちは柴田望洋先生のC++入門くらいなのですが、もし調べるたりステップアップするうえでオススメ書籍があれば教えていただけるとうれしいです! > struct priority_compare { bool operator()(int x, int y) const { return x % 10 < y % 10; } };
episteme

2020/07/09 04:31

関数オブジェクトとかファンクタと呼ばれるもので、あたかも関数のようにふるまいます。 priority_compare pc; bool result = pc(15,52); // 15%10 < 52%10 の結果(bool)を返す。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問