输出单链表
重要性:5
假设我们有一个单链表(如 递归和栈 一章中所述)
let list = {
value: 1,
next: {
value: 2,
next: {
value: 3,
next: {
value: 4,
next: null
}
}
}
};
编写一个函数 printList(list)
,它逐个输出列表项。
使用循环和递归两种方法实现解决方案。
哪个更好:使用递归还是不使用递归?
基于循环的解决方案
基于循环的解决方案变体
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);
现在哪个更好?
从技术上讲,循环更有效。这两个变体做的事情一样,但循环不会为嵌套函数调用消耗资源。
另一方面,递归变体更短,有时更容易理解。