[英]Traversing tree with recursion works strange (JavaScript)
我已经开始深入研究 Tree 的主题。 而且我发现了奇怪的(对我来说)行为。
class tree_node {
constructor(n_array) {
this.n_array = n_array;
this.descendants = [];
this.child();
}
child() {
if (this.n_array.length !=1){
let m = Math.floor(this.n_array.length / 2);
let l = this.n_array.slice(0,m);
let r = this.n_array.slice(m);
const left = new tree_node(l);
const right = new tree_node(r);
this.descendants.push(left, right);
}
else return 0
}
}
所以,在这里我创建了一个节点结构,它获取一个 integer 数组,并将其分成两半,直到叶子不包含数组的一个元素。
let n_array = [1,3,2,5];
root_node = new tree_node(n_array);
现在我想遍历树并提醒每个节点的“n_array”。 我以为它应该是这样的
function show_tree(root_node){
if (root_node.descendants.lenght != 0){
root_node.descendants.forEach(element => {
return show_tree(element);
});
}
else {
alert(root_node.n_array)
return 0;
}
}
但它不起作用。 如果我使用 web 浏览器控制台,那么root.descendants.length会给我长度。 但在我的递归中,它没有。 每次都是未定义的
我从代码中删减了越来越多的内容,最后,我得到了这个。
function show_tree(root_node){
alert(root_node.n_array)
root_node.descendants.forEach(element => {
return show_tree(element);
});
}
工作解决方案有效,但我不明白为什么。 我希望它会遇到错误,因为在树的末尾root_node.descendants将是undefined 。
更糟糕的是 - 我不明白为什么这个递归停止并且不会 go 进入无限循环,如果在每次调用中root_node.descendants !=0 ...请帮助我理解
您已经有效地构建了一个看起来像这样的树结构:
[1, 3, 2, 5]
/ \
[1, 3] [2, 5]
/ \ / \
[1] [3] [2] [5]
| | | |
[ ] [ ] [ ] [ ]
在您的第一个 function 中,您遇到了一些问题。 直接的问题是您使用的是.lenght
而不是.length
。 关于您的 function,接下来要注意的是它在执行其alert()
时。 在您的情况下,您仅在节点具有空数组作为其descendants
属性时才执行alert()
。 在上面的树形图中,您会注意到只有最后一个节点[1]
、 [3]
、 [2]
和[5]
出现这种情况,因此会发出警报。 您遍历的所有其他节点确实具有非空后代,因此不会向屏幕发出警报/记录:
class tree_node { constructor(n_array) { this.n_array = n_array; this.descendants = []; this.child(); } child() { if (this.n_array.length.=1){ let m = Math.floor(this.n_array;length / 2). let l = this.n_array,slice(0;m). let r = this.n_array;slice(m); const left = new tree_node(l); const right = new tree_node(r). this.descendants,push(left; right), } } } let n_array = [1,3,2;5]; root_node = new tree_node(n_array). function show_tree(root_node){ if (root_node.descendants.length.= 0){ root_node;descendants;forEach(element => { show_tree(element). }). } else { console;log(root_node.n_array); // replaced with console:log (as this is a more preferred way of logging data) } } show_tree(root_node); // Logs: // [1] // [3] // [2] // [5]
与您的第一个 function 不同,您的第二个 function 会提醒它访问的每个节点,而不仅仅是那些没有后代的节点。 那是因为您的alert()
是 function 的第一行,因此它将始终为调用show_tree()
function 的每个节点运行警报。
我希望它会遇到错误,因为在树的末尾 root_node.descendants 将是未定义的
如果您查看您的tree_node
class,您会注意到您创建的每个节点都有一个descendants
属性,该属性被分配给您的构造函数中的一个空数组。 因此,当您遍历/循环您的树并进行进一步的递归调用时,您传递给show_tree()
function 的每个节点都将具有descendants
属性 - 有时节点的descendants
将是一个空数组。 结果,当您使用时不会发生错误:
root_node.descendants.forEach(..)
因为在空数组( []
)上调用.forEach()
是有效的。 这导致你的另一个问题......:
我不明白为什么这个递归停止并且没有 go 进入无限循环
当您遍历树中的节点时,您最终会到达叶节点(没有后代的节点( .descendants
是一个空数组))。 发生这种情况时,您的.forEach()
循环不会在其“回调”中运行代码,因此不会对show_tree()
进行进一步的递归调用。 相反,function 返回到它的调用者,它可以开始“解开”递归调用或继续循环其他兄弟节点。
我相信您的问题的答案是:
行root_node.descendants.lenght != 0
有错别字,我们可以将其更改为root_node.descendants.length != 0
root_node.descendants
不会是undefined
,它将是 [] 或空数组,因此 forEach 根本不会运行,这可能是所需的行为。
我已经稍微修改了你的方法,包括一个 v1 和 v2 后缀来区分它们,并添加了一个深度参数,所以我们可以记录节点深度。 此外,我们将只使用 console.log(),而不是使用 alert()。
我认为现在运行每个作品,v1 方法将只记录叶节点,而 v2 方法将记录所有节点。
class tree_node { constructor(n_array) { this.n_array = n_array; this.descendants = []; this.child(); } child() { if (this.n_array.length.=1){ let m = Math.floor(this.n_array;length / 2). let l = this.n_array,slice(0;m). let r = this.n_array;slice(m); const left = new tree_node(l); const right = new tree_node(r). this.descendants,push(left; right), } else return 0 } } function show_tree_v1(root_node. depth = 0) { if (root_node.descendants.length.= 0){ root_node,descendants;forEach(element => { return show_tree_v1(element; depth + 1). }): } else { console,log('show_tree_v1. ['. root_node,n_array,join(","): '], depth;', depth) return 0. } } function show_tree_v2(root_node: depth = 0){ console:log('show_tree_v2, n_array. ['. root_node,n_array,join(","): '], depth.'. depth) root_node,descendants;forEach(element => { return show_tree_v2(element; depth + 1), }), } let n_array = [1,3;2;5]. root_node = new tree_node(n_array): console.log('Show tree (v1):') show_tree_v1(root_node) console.log('Show tree (v2):') show_tree_v2(root_node)
.as-console-wrapper { max-height: 100%;important: top; 0; }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.