给出了这种树数据结构:
const tree = {v:"f", c:[
{v:"b", c:[
{v:"a", c:[]},
{v:"d", c:[
{v:"c", c:[]},
{v:"e", c:[]}
]}
]},
{v:"g", c:[
{v:"i", c:[
{v:"h", c:[]}
]}
]}
]};
到目前为止,我已经设法使用尾递归方法在BFS和DFS预订中遍历它:
// tree fold
const foldl = concat => (valueKey, childKey) => f => acc => tree => {
const next = (acc, [head, ...tail]) => head === undefined
? acc
: next(
f(acc) (head[valueKey]),
concat(head[childKey]) (tail)
);
return next(acc, [tree]);
};
// auxilliary functions
const flip = f => x => y => f(y) (x);
const concat = xs => x => xs.concat(x);
// data
const tree = {v:"f", c:[
{v:"b", c:[
{v:"a", c:[]},
{v:"d", c:[
{v:"c", c:[]},
{v:"e", c:[]}
]}
]},
{v:"g", c:[
{v:"i", c:[
{v:"h", c:[]}
]}
]}
]};
// and run...
console.log("DFS pre-order", foldl(concat) ("v", "c") (concat) ([]) (tree) );
// yields ["f", "b", "a", "d", "c", "e", "g", "i", "h"]
console.log("BFS", foldl(flip(concat)) ("v", "c") (concat) ([]) (tree) );
// yields ["f", "b", "g", "a", "d", "i", "c", "e", "h"]
不幸的是,我无法调整方法,以便它可以另外处理DFS后期订单 - 可以说是一种统一的方法。所需的序列化为["a", "c", "e", "d", "b", "h", "i", "g", "f"]
。任何帮助表示赞赏!
[编辑]
我设法实现了订购后的版本 - 但它仍然不是所有三种情况BFS,DFS预订,DFS后订单的统一解决方案。此外,我不认为我的方法特别优雅。所以我仍然对那些比我更了解递归的人的答案感兴趣。
const foldl = (valueKey, childKey) => f => acc => o => {
const next = (acc, [head, ...tail]) => {
// base case
if (head === undefined) return acc;
// branch (children)
if (head[childKey].length > 0) {
return next(
acc,
concat(head[childKey].concat({v:head[valueKey], c:[]})) (tail)
);
}
// leaf (no children)
return next(f(acc) (head[valueKey]), tail);
};
return next(acc, [o]);
};
foldl("v", "c") (concat) ([]) (tree);
// yields ["a", "c", "e", "d", "b", "h", "i", "g", "f"]
答案 0 :(得分:0)
您需要在添加元素之前递归树,而不是尾递归:
function dfsPost(tree) {
return tree.c.reduce((arr, el) => arr.concat(dfsPost(el)), []).concat(tree.v);
}
dfsPost(tree) // ["a", "c", "e", "d", "b", "h", "i", "g", "f"]
性能较差,但尾递归:您可以执行简单的DFS,但在迭代每个元素时,请使用c.reduceRight()。然后在结果数组上调用reverse()。
function dfsPost(tree) {
return (function dfs(tree) {
return [tree.v].concat(tree.c.reduceRight((arr, el) => arr.concat(dfs(el)), []))
}(tree)).reverse();
}
dfsPost(tree) // ["a", "c", "e", "d", "b", "h", "i", "g", "f"]