- ジェネリックコレクション ページ一覧
LinkedList
System.Collections.Generic.LinkedListクラスは双方向の連結リストのデータ構造を提供するコレクションクラスです。 System.Collections名前空間ではLinkedListに相当するクラス、連結リストのデータ構造を持つ非ジェネリックコレクションクラスは提供されていません。
Listクラスとは異なりインデックスによるアクセスは出来ませんが、挿入と削除の操作はListクラスよりも高速に行えます(ListはO(n):要素数に比例、LinkedListはO(1):要素数によらず常に定数時間)。 LinkedListは、格納される要素の前後関係が重視され、かつ挿入・削除の操作が多いデータ群を扱う場合などに向いています。
基本的な操作
連結リストを実現するために、LinkedListクラスでは個々の要素がLinkedListNodeクラスで表されるノードとして格納されます。 LinkedListに値を追加する場合、その値をもつLinkedListNodeが作成され、LinkedList内の連結リストに追加されます。
各要素=個々のノードは前後のノードを互いに参照する状態で格納されます。 ノードの持つ値はLinkedListNode.Valueプロパティ、次のノードはLinkedListNode.Nextプロパティ、前のノードはLinkedListNode.Previousプロパティにそれぞれ格納されます。 Nextプロパティを次々にたどっていけば、連結リスト内の各ノードを先頭から順に参照していくことができます。 先頭のノード・末尾のノードでは次あるいは前のノードがないため、null
が設定されます。
(null) | [LinkedListNode] | [LinkedListNode] | [LinkedListNode] | (null) | |||
Value = "Alice" | Value = "Bob" | Value = "Charlie" | |||||
←Previous | Next→ | ←Previous | Next→ | ←Previous | Next→ |
Listクラスとは異なり、LinkedListクラスでは要素(=ノード)の前後関係が大きな意味を持ちます。 LinkedListに値(ノード)が格納された後は、その順序を並べ替えることはできません。 並べ替えは削除と挿入によって行う必要があります。 また、LinkedListクラス内のノードは前と次のノードによってのみ位置関係が定まり、インデックスは持ちません。 そのため、インデックスを指定した要素へのアクセス(ランダムアクセス)はできません。 シーケンシャルアクセスのみを行うことができます。
LinkedListの先頭のノードはFirstプロパティ、末尾のノードはLastプロパティとして参照します。 LinkedListが空の場合、FirstプロパティとLastプロパティはともにnull
となります。
ノードの追加
LinkedListへノードを追加するには、下記のメソッドを使います。 直接値を指定して追加することも、値が格納された状態のLinkedListNodeを追加することもできます。 位置を指定して追加するには、次または前となるノードを指定して追加します。
メソッド | 動作 | |
---|---|---|
値の追加 | AddFirst(value) | 値valueを持つノードを作成してLinkedListの先頭に追加する |
AddLast(value) | 値valueを持つノードを作成してLinkedListの末尾に追加する | |
AddBefore(node, value) | LinkedList内のノードnodeの前に、値valueを持つノードを作成して追加する | |
AddAfter(node, value) | LinkedList内のノードnodeの後に、値valueを持つノードを作成して追加する | |
ノードの追加 | AddFirst(node) | LinkedListの先頭にノードnodeを追加する |
AddLast(node) | LinkedListの末尾にノードnodeを追加する | |
AddBefore(node, newNode) | LinkedList内のノードnodeの前に、ノードnewNodeを追加する | |
AddAfter(node, newNode) | LinkedList内のノードnodeの後に、ノードnewNodeを追加する |
追加の際、既に他のLinkedListに属しているノードを追加しようとした場合はInvalidOperationExceptionがスローされます。 また、追加する値を指定するメソッドでは、戻り値として作成・追加されたノードが返されます。
ノードの削除
ノードを削除するには、次のメソッドを使います。 値を指定して削除する場合は、その値をもつ最初のノードが削除されます。
メソッド | 動作 |
---|---|
RemoveFirst() | 先頭にあるノードを削除する |
RemoveLast() | 末尾にあるノードを削除する |
Remove(value) | 値valueを持つ最初のノード(もっとも前方にあるノード)を削除する |
Remove(node) | 指定されたノードnodeを削除する nodeがLinkedListに属していない場合、InvalidOperationExceptionがスローされる |
このほかにも、Clearメソッドを使えばLinkedList内のすべてのノードを削除することができます。
push/pop, shift/unshiftに相当する操作
JavaScriptなどの配列ではpush
/pop
およびshift
/unshift
といった操作を行うことができます。
LinkedListクラスでも同様の操作を行うことができますが、値の取得と同時に削除を行うpop
とshift
に相当するメソッドは用意されていないので、取得と削除は個別に処理する必要があります。
操作 | LinkedListでの相当する操作 |
---|---|
unshift
|
LinkedList.AddFirst() |
shift
|
(get) LinkedList.First.Value + LinkedList.RemoveFirst() |
push
|
LinkedList.AddLast() |
pop
|
(get) LinkedList.Last.Value + LinkedList.RemoveLast() |
push
/pop
およびshift
/unshift
に相当する操作に関しては§.スタックとしての使用および§.キューとしての使用としても解説しています。
列挙操作
既に例にあげたとおり、LinkedListでもforeach文による列挙ができるようになっていますが、インデックスを指定したfor文による列挙は出来ません。 ただし、繰り返し構文とLinkedListNode.Nextプロパティ・LinkedListNode.Previousプロパティを組み合わせることで、任意のノードを起点として列挙を行うことが出来ます。
検索
LinkedList内の要素の検索を行うためには次のメソッドが使えます。 FindメソッドはLinkedList内にあるノードから指定された値を持つ最初のノードを返します。 FindLastメソッドは逆に、指定された値を持つ最後のノードを返します。 いずれのメソッドも、見つからない場合はnull(Nothing)が返されます。
Containsメソッドは、単に指定された値を持つノードがあるかどうかを返します。
スタックとしての使用
.NET Frameworkではスタックのデータ構造を構成するコレクションとしてStackクラスが個別に用意されていますが、LinkedListを使って連結リストをスタックのように扱うこともできます。
LinkedListの先頭に要素を追加していくことによりプッシュ操作となり、先頭から要素を参照・削除していくことでポップ操作となるため、スタックとしての操作を行うことができます。
データ構造としてのスタック、およびStackクラスについてはジェネリックコレクション(5) Stackを参照してください。
キューとしての使用
.NET Frameworkではキューのデータ構造を構成するコレクションとしてQueueクラスが個別に用意されていますが、LinkedListを使って連結リストをキューのように扱うこともできます。
LinkedListの末尾に要素を追加していくことによりエンキュー操作となり、先頭から要素を参照・削除していくことでデキュー操作となるため、キューとしての操作を行うことができます。
データ構造としてのキュー、およびQueueクラスについてはジェネリックコレクション(6) Queueを参照してください。