単一連結リストを出力する
重要度: 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つの変種は同じことをしますが、ループはネストされた関数呼び出しにリソースを費やしません。
一方、再帰的変種はより短く、理解しやすい場合があります。