レッスンに戻る

単一連結リストを出力する

重要度: 5

再帰とスタック章で 説明した単一連結リストがあるとします

let list = {
  value: 1,
  next: {
    value: 2,
    next: {
      value: 3,
      next: {
        value: 4,
        next: null
      }
    }
  }
};

リストの項目を1つずつ出力する関数printList(list)を作成します。

ループと再帰を使用した、2つのバージョンのソリューションを作成します。

優れた方法は再帰を使うか使わないかどちらですか?

ループベースのソリューション

ソリューションのループベースの変種

let list = {
  value: 1,
  next: {
    value: 2,
    next: {
      value: 3,
      next: {
        value: 4,
        next: null
      }
    }
  }
};

function printList(list) {
  let tmp = list;

  while (tmp) {
    alert(tmp.value);
    tmp = tmp.next;
  }

}

printList(list);

リストを移動するには一時変数tmpを使用することに注意してください。実際には、代わりに関数パラメータlistを使用できます

function printList(list) {

  while(list) {
    alert(list.value);
    list = list.next;
  }

}

…ただし、それは賢明ではありません。将来、関数を拡張したり、リストで別の何かを行う必要があるかもしれません。listを変更すると、そのような機能が失われます。

適切な変数名の話題ですが、ここではlistはリストそれ自体です。その最初の要素。そして、それはそのように残るべきです。それは明確で信頼できます。

一方、tmpの役割はforループのiのように、リストの走査だけです。

再帰的ソリューション

printList(list)の再帰変種は単純なロジックに従います。リストを出力するには、現在の要素listを出力してから、list.nextに対して同じことを行う必要があります

let list = {
  value: 1,
  next: {
    value: 2,
    next: {
      value: 3,
      next: {
        value: 4,
        next: null
      }
    }
  }
};

function printList(list) {

  alert(list.value); // output the current item

  if (list.next) {
    printList(list.next); // do the same for the rest of the list
  }

}

printList(list);

さて、どちらが良いでしょうか?

技術的には、ループの方が効果的です。これら2つの変種は同じことをしますが、ループはネストされた関数呼び出しにリソースを費やしません。

一方、再帰的変種はより短く、理解しやすい場合があります。