両端キューは先頭または末尾で要素を追加・削除できるキューです。

通常のキューは要素を追加するときは末尾からしかできず、取り出すときは先頭からしかできません。通常のリスト(C#のList<T>)は任意の場所で要素の加除ができますが、末尾以外の部分だと処理に時間がかかります。LinkedListは任意の場所で要素の加除を高速におこなうことができますが、ランダムアクセスができません。

ここでは先頭または末尾で要素を追加・削除とランダムアクセスが高速でできるデータ構造の実装を目標とします。

配列デック

ここでは内部処理に配列を使います。配列は定数時間でランダムアクセスが可能です。リングバッファのようなものを作り、ここに両端キューの内容を格納し、バッファが満杯になったときだけサイズを拡大するようにします。リングバッファとは配列の最後の次の要素が先頭になっている配列のことです。

ArrayDeque<T>クラス

クラス名はArrayDeque<T>とし、内部処理で使う配列 Array と格納されたデータの先頭に相当する部分を表す FirstIndex と 最後の次に当たる部分を表す NextToLastIndex を定義します。

Lengthプロパティとインデクサ

FirstIndex と NextToLastIndex から実際に格納されているデータの個数がわかります(Lengthプロパティ)。またFirstIndexからランダムアクセスするときはArrayのどの部分にアクセスすればいいかもわかります(インデクサ)。

AddFirst, AddLast, RemoveFirst, RemoveLastメソッド

要素の加除をおこなうときはArray[i]を更新するとともにFirstIndex と NextToLastIndex の値も変更します。これで両端部分であれば要素の加除が高速でできるようになるとともに、ランダムアクセスもできるようになりました。

Growメソッド

要素を追加した結果、Arrayのサイズでは足りなくなった場合はArrayを拡張します(もっと大きなサイズの新しい配列を生成してArrayに代える)。

実装

ArrayDequeクラスを以下のように定義します。

ためしにArrayDequeクラスを使ってみます。