以下是我正在使用的树以及所需的字符串序列化的直观表示形式:
这是一个递归解决方案:
function* serialize(root) {
if (root.length === 0)
return;
const [x, xs] = root;
yield x;
for (let i = 0; i < xs.length; i++)
yield* serialize(xs[i]);
yield ")";
}
const Node = (x, ...xs) => ([x, xs]);
const tree = Node("a",
Node("b",
Node("e"),
Node("f",
Node("k"))),
Node("c"),
Node("d",
Node("g"),
Node("h"),
Node("i"),
Node("j")));
console.log(
Array.from(serialize(tree)).join("")); // abe)fk)))c)dg)h)i)j)))
显然,它可以工作,但对于非常深的树来说并不安全。如何将其转换为迭代的对应项?
我知道我需要一个堆栈。但我不知道细节。我对这种转换的基本机制特别感兴趣。
我设法创建了一个迭代的预遍历,但是奇怪的是,这对迭代序列化没有帮助:
const Node = (x, ...xs) => ([x, xs]);
const tree = Node("a",
Node("b",
Node("e"),
Node("f",
Node("k"))),
Node("c"),
Node("d",
Node("g"),
Node("h"),
Node("i"),
Node("j")));
function* preOrderIt(root) {
if (root.length === 0)
return;
const stack = [root];
while (stack.length > 0) {
let [x, xs] = stack.pop();
for (let i = xs.length - 1; i >= 0; i--)
stack.push(xs[i]);
yield x;
}
}
console.log(
Array.from(preOrderIt(tree)).join("")); // abefkcdghij
答案 0 :(得分:2)
您的序列化基本上向每个节点添加了一个额外的虚拟子节点,因此您在迭代时必须“访问”它:
const Node = (x, ...xs) => ([x, xs]);
const tree = Node("a",
Node("b",
Node("e"),
Node("f",
Node("k"))),
Node("c"),
Node("d",
Node("g"),
Node("h"),
Node("i"),
Node("j")));
function* preOrderIt(root) {
if (root.length === 0)
return;
const stack = [root];
while (stack.length > 0) {
let [x, xs] = stack.pop();
if (x !== ')') // <-
stack.push([')', []]); // <-
for (let i = xs.length - 1; i >= 0; i--)
stack.push(xs[i]);
yield x;
}
}
console.log(
Array.from(preOrderIt(tree)).join(""));
答案 1 :(得分:1)
一种不同的方法,通过对级别使用数组并首先迭代更深的级别。
function s(root) {
var i = 0,
node,
levels = [[root]],
result = '';
while (i !== -1) {
[node, ...levels[i]] = levels[i];
if (node) {
result += node[0];
if (node[1].length) {
levels[++i] = node[1];
continue;
}
} else {
i--;
}
result += ')';
}
return result.slice(0, -1); remove extra bracket for the outer missing array
}
const
node = (x, ...xs) => ([x, xs]),
tree = node("a", node("b", node("e"), node("f", node("k"))), node("c"), node("d", node("g"), node("h"), node("i"), node("j"))),
result = s(tree);
console.log(result);
答案 2 :(得分:0)
一种选择是链接节点。这样一来,您就可以遍历树而无需保持位置不变
const Node = (value, ...children) => {
const node = { value, children };
children.forEach(child => child.parent = node);
if(children.length > 1)
children.reduceRight((curr, prev) => ((prev.next = curr), prev));
return node;
};
这有什么帮助?好吧:
function serialize(node) {
let result = node.value;
while(node) {
// Deep first
while(node.children[0]) {
node = node.children[0];
result += node.value;
}
// then right
if(node.next) {
node = node.next;
result += ")" + node.value;
} else {
// and up at the last node
while(node && !node.next) {
node = node.parent;
result += ")";
}
result += ")";
if(node) {
node = node.next;
result += node.value;
}
}
}
return result;
}