Given is this tree data structure:
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:[]}
]}
]}
]};
So far I've managed to traverse it in BFS and DFS pre-order with a tail recursive approach:
// 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"]
Unfortunately, I 'm not able to adapt the approach so that it can handle DFS post-order in addition - a unified approach, so to speak. The desired serialization is ["a", "c", "e", "d", "b", "h", "i", "g", "f"]
. Any help is appreciated!
[EDIT]
I managed to implement the post-order version - but it still not a unified solution for all three cases BFS, DFS pre-order, DFS post-order. Besides, I don't think my approach is particularly elegant. So I'm still interested in answers from people who have a better understanding of recursion than me.
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"]
Instead of tail-recursion, you want to recurse down the tree before adding the elements:
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"]
Less performant, but tail recursive: You can do a simple DFS, but when iterating over each element, use c.reduceRight(). Then call reverse() on the resulting array.
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"]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.