コンピュータサイエンスにおいて、キューは、順序付けられたエンティティの集合として機能する抽象データ型です。慣例として、要素が追加されるキューの末尾はキューのバック、テール、またはリアと呼ばれます。要素が削除されるキューの末尾はキューのヘッドまたはフロントと呼ばれます。キューという名前は、商品やサービスを待つために列に並ぶ人々を表す言葉に由来しています。キューは主に2つの操作をサポートします。
その他の操作も許可される場合があり、多くの場合、デキューせずに次にデキューされる要素の値を返すピーク操作やフロント操作が含まれます。
キューの操作は、キューに最初に追加された要素が最初に削除されるため、先入れ先出し (FIFO) データ構造となります。これは、新しい要素が追加されると、新しい要素を削除する前に、それ以前に追加されたすべての要素が削除されなければならないという要件と同等です。キューは線形データ構造、より抽象的にはシーケンシャルコレクションの一例です。キューはコンピュータプログラムでよく使用され、アクセスルーチンと結合されたデータ構造として、抽象データ構造として、またはオブジェクト指向言語ではクラスとして実装されます。キューは、循環バッファとリンクリストとして、またはスタックポインタとベースポインタの両方を使用して実装できます。
キューは、コンピュータサイエンス、輸送、オペレーションズリサーチなどの分野で、データ、オブジェクト、人物、イベントといった様々なエンティティを格納し、後で処理するために保持する役割を果たします。これらの分野では、キューはバッファとして機能します。また、幅優先探索の実装にもキューが用いられます。
理論的には、キューの特徴の一つは、特定の容量を持たないことである。既にいくつの要素が含まれていても、常に新しい要素を追加できる。また、キューが空になることもあり、その場合は、新しい要素が再び追加されるまで、要素を削除することは不可能となる。
固定長配列は容量に制限がありますが、キューの先頭に向かって項目をコピーする必要があるというのは事実ではありません。配列を閉じた円にして、先頭と末尾をその円の中で無限に漂わせるという単純なトリックにより、配列に格納されている項目を移動する必要がなくなります。配列のサイズが n の場合、インデックスを n で割った余りを計算すると、配列は円になります。これは、高水準言語でキューを構築する概念的に最も単純な方法ですが、配列のインデックスをゼロと配列のサイズと比較する必要があるため、処理速度が少し遅くなることは認めざるを得ません。これは、配列のインデックスが範囲外かどうかをチェックするのにかかる時間と同程度です。一部の言語では範囲外チェックが行われますが、これは、手っ取り早く実装する場合や、ポインタ構文を持たない高水準言語の場合に、間違いなく選択される方法です。配列のサイズは事前に宣言する必要がありますが、オーバーフローが発生した場合に宣言された配列のサイズを単純に 2 倍にする実装もあります。オブジェクトまたはポインタを持つほとんどの最新の言語は、動的リストを実装するか、ライブラリが付属しています。このようなデータ構造では、メモリ制約以外に固定容量制限が指定されていない場合があります。キューオーバーフローは、満杯のキューに要素を追加しようとしたときに発生し、キューアンダーフローは、空のキューから要素を削除しようとしたときに発生します。
制限付きキューとは、アイテム数が固定されているキューのことです。[ 1 ]
FIFOキューにはいくつかの効率的な実装があります。効率的な実装とは、エンキューとデキューの操作を時間。
キューは、別のデータ型として実装される場合もあれば、両端キュー(deque)の特殊なケースとして扱われ、別々に実装されない場合もあります。たとえば、PerlやRuby ではpush()配列を両端からプッシュおよびポップできるため、関数を使用してリストをエンキューおよびデキューできます (または、その逆で、およびをshift()使用できます)。[ 2 ]ただし、場合によってはこれらの操作は効率的ではありません。unshift()pop()
C++ の標準テンプレートライブラリはstd::queue<T>、プッシュ/ポップ操作のみに制限されたテンプレートクラスを提供します。J2SE5.0 以降、Java のライブラリにはQueueキュー操作を指定するインターフェースが含まれており、実装クラスにLinkedListは (J2SE 1.6 以降)が含まれますArrayDeque。PHP にはSplQueueクラスがあり、 beanstalk'dやGearmanなどのサードパーティライブラリがあります。
![]()
TypeScriptで実装されたシンプルなキュー:
class Queue < T > { private items : T [] = [];enqueue ( element : T ) : void { this.items.push ( element ) ; }dequeue ( ) : T | undefined { return this.items.shift ( ) ; }isEmpty ( ) : boolean { return this.items.length === 0 ; } }キューは純粋関数型データ構造としても実装できます。[ 3 ]実装方法は2つあります。最初の実装では、平均して1回の操作あたり。つまり、償却時間はしかし、個々の操作には時間がかかる場合がありますどこはキュー内の要素数です。2番目の実装はリアルタイムキュー[ 4 ]と呼ばれ、最悪の場合O(1)の時間で操作を行い、キューを永続化できます。これはより複雑な実装であり、メモ化を備えた遅延リストが必要です。
このキューのデータは、2 つの単方向リンクリストに格納されます。そしてリストキューの先頭部分を保持します。リスト残りの要素(キューの末尾とも呼ばれる)を逆順に保持します。 の先頭にノードを追加することで、キューの先頭に簡単に挿入できます。そして、もし空でない場合、先頭のノードを削除することでキューの末尾から簡単に削除できます。。 いつリストは空です反転して割り当てられるそして、削除されました。
挿入(「エンキュー」)は常に時間。削除(「デキュー」)には時間がかかります。リストが空ではありません。空の場合、逆はどこは、しかし、それは償却時間、なぜなら挿入する必要があり、挿入されたタイミングの逆の順序で各要素に一定のコストを割り当てることができます。
リアルタイムキューは償却なしの全操作にかかる時間。この議論は技術的なものになるので、次の点に留意してください。リスト、長さを表す。空のリストを表し、先頭がそしてその尻尾は。
キューの実装に使用されるデータ構造は、3つの単方向連結リストで構成されています。どこ列の先頭であり、は、逆順のキューの最後尾です。構造の不変条件は、の後ろ側はなしで最初の要素、つまり列の最後尾するとほぼ要素を挿入するにほぼほぼそう言われているのは、どちらの結果も、補助機能不変条件を満たすためには、次に を呼び出す必要があります。 2 つのケースを考慮する必要があります。空のリストの場合、、あるいはそうではない。正式な定義はそしてどこはに続く逆になった。
電話をかけましょう関数を返すに続く逆転した。さらに、なぜなら、この関数が呼び出されるときにそうなるからです。より正確には、遅延関数を定義します。これは、次のような3つのリストを入力として受け取ります。、そして連結したものを返します、 の逆転して。 それから回転の帰納的定義はそして実行時間はしかし、遅延評価が使用されているため、計算結果は計算によって強制されるまで遅延されます。
リストデータ構造には 2 つの目的があります。このリストは、、 確かに、かつその場合に限りは空のリストです。このカウンターを使用すると、末尾のリストが先頭のリストより長くなることはありません。さらに、これは、(遅延)リストの一部の計算を強制する各期間中そして操作。したがって、リスト完全に強制されている。そうでない場合、内部表現は追加の追加の追加の...の追加の追加のようなものになる可能性があり、強制するともはや定数時間の操作ではなくなります。