web-dev-qa-db-ja.com

PriorityQueueを反復処理する方法は?

for (Event e : pq)

優先順位で繰り返されません。

while(!pq.isEmpty()){
  Event e = pq.poll();
}

これは機能しますが、キューを空にします。

28
simpatico

Javadocs から:

メソッドiterator()で提供されるイテレータは、特定の順序でPriorityQueueの要素を走査することを保証されていません。順序走査が必要な場合は、Arrays.sort(pq.toArray())の使用を検討してください。

おそらく他の同等のメカニズムがあります。

24

基礎となる実装のために、この順序で優先度キューを通過することはできません(Javaの最小ヒープだと思います)。ソートされた配列ではないため、ある要素から優先順位の低い要素に移動できます。ピークは最小の要素を見るため、一定の時間です。次の(O(log n)時間で)を取得するには、must最小要素をデキューします。デキューは、その要素を取り出すだけの問題ではなく、要素の優先度が最も低い要素を最初に持ってくるために、基礎となる構造が再配置されます。

また、優先度キュー全体を通過するのはO(n log(n))操作です。したがって、キュー内のすべての要素を取得して並べ替えるだけでなく(O(n log(n)))、必要に応じてそれらを通過することもできます。唯一の欠点は、キューの余分なコピーを保持していることです。

それでも、この方法でデータを走査する必要がある場合、優先度キューはニーズに合ったデータ構造ではない可能性があります。

23
Alex Florescu

ヒープベースの優先度キューは、最初の要素が最高/最低であることのみを保証します。安価な(つまりO(n))ソートされた形式で要素を取得する方法はありません。

これを頻繁に行う必要がある場合は、要素をソートされた形式で維持する構造の使用を検討してください。たとえば、Java.util.TreeSetを使用し、pollFirst()/pollLast()の代わりに peek() またはpoll()を使用します

8
Dilum Ranatunga

以前のポスターはすべてを述べましたが、誰も完全な実例を挙げませんでした(pqをコピーする以外)。

Event[] events = pq.toArray(new Event[pq.size()]);
Arrays.sort(events, pq.comparator());
for (Event e : events) {
    System.out.println(e);
}
1
kubpica

そのため、リストでpriorityQueueを取得してからソートすることは、前述のように適切なオプションです。イテレータが予期しない結果をもたらす理由の詳細を次に示します。

反復子は、基になるデータ構造(ArrayListと同様)から出力されるため、正しい順序で要素を返しません。 ArrayListには、データがBinaryHeapのArray実装に格納されるのと同じ方法でデータが格納されます。例えば:

PriorityQueue<Integer> pq = new PriorityQueue<>();
ArrayList<Integer> test = new ArrayList(Arrays.asList(6,12,7,9,2));
test.forEach(x -> pq.add(x)); 
System.out.println("Priority Queue:- "+pq); [2, 6, 7, 12, 9]

ここで、childOf(i)は2 * i + 1および2 * i + 2であり、parentOf(i)は(i-1)/ 2です

0
yash jain

最近、私は同じ問題を抱えていました。優先度キューの特定のオブジェクトを使用して、残りの要素を保持したいです。

1)newPriorityQueueを作成しました。 2)イテレータを使用してoldQueueのすべての要素を解析します3)oldQueue.poll()メソッドを使用して要素を取得します4)要素を挿入します3)使用しない場合はnewPriorityQueueに挿入します.

 Queue<String> newQueue = new PriorityQueue<String>(); 
    // Assuming that oldQueue have some data in it.

    Iterator<String> itr = oldQueue.iterator();
    while(itr.hasNext()){
        String str = oldQueue.poll();
        // do some processing with str
        if(strNotUsed){
            newQueue.offer(str);
        }
    }

最終的に、oldQueueは空になります。 @その他:-同じことができるなら、より良い方法を提案してください。正しい順序で要素を返さないため、反復子を使用できません。

0
novice

peek()メソッドはキューから何も削除しませんが、このため、IS empty。まで空の値を取得し続けます。 whileループの後は空だったため、この結論が得られました。

これを行う唯一の方法は、自分でソートすることです。次のように、元のコンパレータを取得できます。

Event[] events = Arrays.sort(pq.toArray(), pq.comparator());
for (Event e : events) {
    // do stuff
}
0
xthexder

キューのコピーを作成し、ループでポーリングできます。この例では、pqは元の優先度キューです。

PriorityQueue<Your_class> pqCopy = new PriorityQueue<Your_class>(pq);
while(!pqCopy.isEmpty()){
    Your_Class obj = pqCopy.poll();
    // obj is the next ordered item in the queue
    .....
}
0
Carlos Cuesta