連結リスト

各要素が次の要素へのポインタを持つ線形データ構造

データ構造アルゴリズム

連結リストとは

連結リスト (Linked List) は、各要素 (ノード) が値と次のノードへのポインタを持つ線形データ構造である。配列と異なりメモリ上で連続している必要がなく、先頭・末尾への挿入・削除が O(1) で行える。

配列との比較

配列との主な違いを以下に比較する。

操作 配列 連結リスト
インデックスアクセス O(1) O(n)
先頭への挿入 O(n) O(1)
末尾への挿入 O(1) (動的配列) O(1) (末尾ポインタあり)
中間への挿入 O(n) O(1) (位置が既知)
検索 O(n) O(n)
メモリ 連続、キャッシュ効率が高い 分散、ポインタのオーバーヘッド

種類

連結リストには、ポインタの持ち方によって 3 つの代表的なバリエーションがある。

単方向: [A][B][C] → null

双方向: null ← [A][B][C] → null

循環: [A][B][C][A] (先頭に戻る)

TypeScript での実装

単方向連結リストの基本操作を TypeScript で実装すると次のようになる。

class ListNode<T> {
  constructor(public value: T, public next: ListNode<T> | null = null) {}
}

class LinkedList<T> {
  private head: ListNode<T> | null = null;

  prepend(value: T) {
    this.head = new ListNode(value, this.head);
  }

  find(value: T): ListNode<T> | null {
    let current = this.head;
    while (current) {
      if (current.value === value) return current;
      current = current.next;
    }
    return null;
  }

  toArray(): T[] {
    const result: T[] = [];
    let current = this.head;
    while (current) {
      result.push(current.value);
      current = current.next;
    }
    return result;
  }
}

実際の利用場面

代表的な利用場面を以下にまとめる。

場面 理由
LRU キャッシュ 双方向リスト + ハッシュマップで O(1) の挿入・削除
ブラウザの履歴 前へ/次へのナビゲーション (双方向リスト)
Undo/Redo 操作履歴の管理
メモリアロケータ フリーリスト (空きメモリブロックの管理)

現代の開発での位置づけ

JavaScript/TypeScript では配列 (Array) が動的配列として実装されており、ほとんどのケースで配列の方が高速だ。連結リストが有利なのは、先頭への頻繁な挿入・削除が必要な場合に限られる。コーディング面接では頻出のデータ構造。

より深く学ぶには関連書籍が役立つ。

この記事は役に立ちましたか?

関連用語

関連する記事