みんなのデータ構造(紙書籍+電子書籍) – 技術書出版と販売のラムダノート
これまでのメモ
2章の後半をすっ飛ばして、第3章の連結リストに入る。
今回は「[P55] 3.1 SLList: 単方向連結リスト」。
TypeScript によるソースコード
https://github.com/zaki-yama/open-data-structures-typescript/blob/master/src/SLList.ts
メモ
連結リストとは
第3章でも第2章と同じくListインターフェースの実装を扱うが、データ構造として配列ではなく連結リストを使う。
連結リストとは、「実際のデータ」と「他の要素への参照(ポインタ)」を持った ノード を繋げて列を作ったもの。
Listインターフェースの実装に連結リストを使うのは、配列を使う場合と比較して以下の長所と短所がある。
- 長所:動的な操作がしやすい
- ノードへの参照
u
があれば、u
の削除やu
の隣へのノードの挿入が定数時間でできる(配列はi
番めに入れるかによってO(1 + min{i, n - i})
の実行時間だった)
- ノードへの参照
- 短所:
get(i)
やset(i, x)
がすべての要素に対して定数時間ではなくなる
SLList(単方向連結リスト)とは
文字通り、ノードが一方向への参照しか持たない連結リストのこと。
各ノードu
は
- データ
u.x
- 次のノードへの参照
u.next
(末尾はnull
)
を持つ。
SLListの実行時間
SLListはStackとQueueインターフェースを実装する。
push(x)
、pop()
、add(x)
、remove()
の実行時間はいずれも O(1)
。
SLListでStackを実装する
push(x)
操作は
- 新しいノード
u
を作成する u.next
はそれまでのhead
をセットhead
をu
にするn++
なので、定数時間で終わる。
pop()
操作は
head
を削除head
をhead.next
に移動n--
SLListでQueueを実装する
省略。
先頭の削除はStackのpop()
と同じだし、末尾への追加はtail.next = u
とするだけ。
SLListの欠点
SLListでDequeの操作を実装しようとしたとき、末尾を削除する操作が足りない。
末尾を削除するためにはtail
が指すノードを1つ前にずらす必要があるが、このようなノード(u.next = tail
であるノード)を見つけるには先頭から順にノードをたどらなくてはいけない。