通常、本番ソフトウェアのどこでDequeを使用しますか?


21

ソフトウェアアプリケーションでスタック、キュー、およびツリーを使用する場所についてはかなりよく知っていますが、Deque(Double Ended Queue)を使用したことはありません。通常、野生ではどこで遭遇しますか?キューと同じ場所にありますが、余分な不満がありますか?



このスレッドには混乱があるようです。インターネット上の「deque」は両端キューです(ウィキペディアはリンクリストの実装に言及しています)。ただし、C ++ STLでは、「std :: deque」はデータブロックの配列として実装される配列のような構造です。std :: vectorに似たランダムアクセスを提供しますが、データの追加時にブロックを追加し、既存のデータの再割り当てと移動を行わないため、サイズ変更機能はstd :: listの機能に近くなります。
DXM

1
@DXM:ただし、STL両端キューはまだ両端キューであり、(実装に応じて)終了時の操作が高速になります。中央へのアクセスも提供することは、その主要な操作がキューのように少なくなることではありません。
gbjbaanb

@gbjbaanb:私が言っているのは、3つのクラスのパブリックインターフェイスを見れば:std :: vector、std :: list(またはstd :: queue)およびstd :: deque、std :: vectorが表示されます。およびstd :: dequeは、同一のパブリックインターフェイスと同一の機能を備えています(std :: dequeは、メモリフットプリントが大きくなることを犠牲にして、わずかに柔軟性があります)。一方、std :: listおよびstd :: queueは、それぞれCSカウンターパート、リンクリスト、およびキューのように動作します。CS deque!= std :: deque
DXM

- shiv.mymailことで、この答えは、より実用的なI見つける stackoverflow.com/questions/3880254/...
roottraveller

回答:


21

dequeの使用方法の1つは、アイテムを「エージング」することです。通常、元に戻す機能または履歴機能として使用されます。新しいアクションが両端キューに挿入されます。最も古いアイテムが前面にあります。dequeのサイズの制限により、新しいアイテムが挿入されると(最古のアイテムが古くなる)、ある時点で前面のアイテムが強制的に削除されます。次に、最古のアイテムと最新のアイテムを即座に把握して、O(1)でフロントを削除し、最も古いアクションをコミットするか、O(1)で元に戻すため、構造の両端にすばやくアクセスできます。


ここでは、両端キューが使用される/必要になるとは思わない。単純な(おそらくサイズ制限のある)スタックで十分です。
コンラッドルドルフ

2
@Konrad単純なスタックでアイテムをどのようにエージングしますか?(つまり、「古すぎる」コマンドをどのように削除しますか?)
Andres F.

@AndresF。年齢はスタックサイズとは無関係ですか?もしそうなら、私はこのデータ構造について聞いたことがない。それ以外の場合、単に両端キューの観点から実装できる固定サイズのスタック、または単純に固定サイズスタックと呼ばれるより単純なデータ構造を仮定することによって実装できます。
コンラッドルドルフ

したがって、deque 結局便利です;)固定サイズのスタックについて聞いたことはありません(つまり、最も古いアイテムを削除するという意味です)。それは理にかなっていますが、それは通常「スタック」が意味するものではなく、それが実際に単純であるかどうかはまだ
Andres F.

これは元の質問のコメントに投稿されました:en.wikipedia.org/wiki/Double-ended_queueこれは単なる両端キューです。上記で説明した方法で実際に使用しました(そのため、投稿しました)。真のスタックでは、プッシュ、ポップ、トップ、ピークの操作のみが必要です(他の人も議論できますが、これは一般的にはそうです)。スタックの最下部に何があるか、最下部にアクセスする方法すら知らないはずです。「固定サイズのスタック」では、古いアイテムをいっぱいにしたときにエージングするのではなく、単にスタックオーバーフローを生成します。
jmq

1

素晴らしい質問です。CS 102のコースで、両端待ち行列の単一のアプリケーションについて言及したことを思い出せません。

今日まで、私が知っている唯一のアプリケーションは、Wikipediaの記事で言及されている作品を盗むスケジューラーです。

基本的に次のように機能します。

通常のシングルスレッドプロシージャモデルでは、すべての関数呼び出しは、いわゆる呼び出しスタックにアクティベーションレコードをプッシュします。アクティベーションレコードには、その呼び出しのローカル変数とパラメーターが含まれます。メソッドの呼び出しが完了すると(「戻る」)、最後のアクティベーションレコードが呼び出しスタックからポップされます。

これは、再帰が実装される方法であるため、特に重要です。再帰の構造は、呼び出しスタックの現在の状態で表されます。

再帰アルゴリズムを並列化する場合、呼び出しスタックを呼び出しキューに置き換えることにより、このプロパティを活用できます。計算内のすべてのスレッドは、独自の呼び出しキューを取得し、順次実行のようにアクティベーションレコードをプッシュおよびポップします。

しかし、スレッドがその作業を完了すると(=呼び出しキューは空になります)、「間違った」端から削除することにより、そのスレッドの呼び出しキューからアクティベーションレコードを削除することにより、別のスレッドから作業を盗みます。

基本的に、コールキューは2つのスレッドを処理する2つのコールスタックとして機能します。


これのソースはありますか?興味深いですね。
kyjelly90210

1
@ Richard1987ウィキペディアの記事は元の論文を引用しています。いくつかの実装があります。たとえば、GNU c ++ stdlib並列拡張ワークスティール実装(ただし、コードを読むのは恐ろしいです)や、実際の一般的な分割&征服の並列実装(後者は非常に慣用的なプログラミングスタイルを使用します)図書館に特有で読みにくい)
コンラッドルドルフ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.