我有一个典型的树数据结构,如下所示:
[
{
data: object,
subs:
[ ...other objects... ]
},
...other objects...
]
它可以有任何形状和数量的节点。
我写了一个方法,它应该递归地查找并返回根 r 和给定对象 o 之间的路径(中间对象数组)。 (是否包括 r 和 o 我不在乎)
public getPath(tree: Array<object>, o: object): Array<object> {
let path: Array<object> = [];
function f(subtree: Array<object>): void {
for (let node of subtree) {
path.push(node['data']);
if (node['data'] == o) return;
else if (node['subs'].length > 0) f(node['subs']);
else path = [];
}
}
f(tree);
return path;
}
基本上我的想法是
结果:
答案 0 :(得分:2)
您的代码存在缺陷,即您正在使用全局(f
的范围)path
数组。问题是如果节点不匹配则清除整个阵列,而您应该只切断当前部分。有两种方法可以达到你想要的效果:首先是让f
接受一个数组path
,它复制并递归传递直到它找到对象,另一种方法是最好的方法是使用调用堆栈(由递归创建):
public getPath(tree: Array<object>, o: object): Array<object> {
function f(subtree: Array<object>) { // I don't know typescript, so specify the return type as (Array<object> or null)
for (let node of subtree) {
if (node.data == o) { // if this is the node we're looking for
return [node]; // return an array (which will be our path), here you can either return [] to exclude the matched node (o) or [node] to include it
} else if(node.subs.length) { // not the node we are looking for, but it has children, so let check'em out
let result = f(node.subs); // result will either be an array (if we recursively found something), or null otherwise
if(result) { // if we found something, then result will be the path from the current node to the object o (the current node not included)
result.unshift(node); // we include the current node by pushing it into the result array (pushing it to the first position)
return result; // return result (an array) to signal successfulness
}
}
}
return null; // the object o not found in this subtree, return null to signal unsuccessfullness. Kind of redundant, because undefined is returned by default, so feel free to remove it
}
return f(tree);
}