没有循环的尾递归树遍历
Tail Recursive Tree Traversal without Loops
我想递归遍历下面的树结构尾部而不回退到循环:
const o = {x:0,c:[{x:1,c:[{x:2,c:[{x:3},{x:4,c:[{x:5}]},{x:6}]},{x:7},{x:8}]},{x:9}]};
0
/ \
1 9
/ | \
2 7 8
/ | \
3 4 6
|
5
想要的结果:/0/1/2/3/4/5/6/7/8/9
我想需要闭包才能启用尾递归。到目前为止我已经试过了:
const traverse = o => {
const nextDepth = (o, index, acc) => {
const nextBreadth = () => o["c"] && o["c"][index + 1]
? nextDepth(o["c"][index + 1], index + 1, acc)
: acc;
acc = o["c"]
? nextDepth(o["c"][0], index, acc + "/" + o["x"]) // not in tail pos
: acc + "/" + o["x"];
return nextBreadth();
};
return nextDepth(o, 0, "");
};
traverse(o); // /0/1/2/3/4/5/7/9
兄弟姐妹遍历不正确。如何做到这一点?
正如@Bergi 所写,如果您手动维护堆栈,解决方案很简单。
const o = {x:0,c:[{x:1,c:[{x:2,c:[{x:3},{x:4,c:[{x:5}]},{x:6}]},{x:7},{x:8}]},{x:9}]}
const traverse = g => {
const dfs = (stack, head) => (head.c || []).concat(stack)
const loop = (acc, stack) => {
if (stack.length === 0) {
return acc
}
const [head, ...tail] = stack
return loop(`${acc}/${head.x}`, dfs(tail, head))
}
return loop('', [g])
}
console.log(traverse(o))
console.log(traverse(o) === '/0/1/2/3/4/5/6/7/8/9')
我想递归遍历下面的树结构尾部而不回退到循环:
const o = {x:0,c:[{x:1,c:[{x:2,c:[{x:3},{x:4,c:[{x:5}]},{x:6}]},{x:7},{x:8}]},{x:9}]};
0
/ \
1 9
/ | \
2 7 8
/ | \
3 4 6
|
5
想要的结果:/0/1/2/3/4/5/6/7/8/9
我想需要闭包才能启用尾递归。到目前为止我已经试过了:
const traverse = o => {
const nextDepth = (o, index, acc) => {
const nextBreadth = () => o["c"] && o["c"][index + 1]
? nextDepth(o["c"][index + 1], index + 1, acc)
: acc;
acc = o["c"]
? nextDepth(o["c"][0], index, acc + "/" + o["x"]) // not in tail pos
: acc + "/" + o["x"];
return nextBreadth();
};
return nextDepth(o, 0, "");
};
traverse(o); // /0/1/2/3/4/5/7/9
兄弟姐妹遍历不正确。如何做到这一点?
正如@Bergi 所写,如果您手动维护堆栈,解决方案很简单。
const o = {x:0,c:[{x:1,c:[{x:2,c:[{x:3},{x:4,c:[{x:5}]},{x:6}]},{x:7},{x:8}]},{x:9}]}
const traverse = g => {
const dfs = (stack, head) => (head.c || []).concat(stack)
const loop = (acc, stack) => {
if (stack.length === 0) {
return acc
}
const [head, ...tail] = stack
return loop(`${acc}/${head.x}`, dfs(tail, head))
}
return loop('', [g])
}
console.log(traverse(o))
console.log(traverse(o) === '/0/1/2/3/4/5/6/7/8/9')