我必须从平衡的括号中找到树的高度并找到保护编号(或仅生成树)。
例如:
()()()()创建树,就像一个高度为3的列表。
我不知道如何将括号转换为树。我找到了一些“答案”:
http://www.cs.utsa.edu/~wagner/knuth/fasc4a.pdf(第二页包含具有4个节点的树的所有示例)
段落-二叉树,森林,非交叉对:
https://sahandsaba.com/interview-question-generating-all-balanced-parentheses.html
但是,我仍然不知道如何从这样定义的括号创建树。我觉得在Knuth中,作者将其视为显而易见的东西。
我想念某件事还是不是那么简单?
有必要先创建一个森林然后再创建一个二叉树吗?
答案 0 :(得分:2)
一对圆括号代表一个节点。这些括号中的 中出现的内容表示其左子节点的子树(根据相同的规则)。这些括号右边显示的是该节点的右子节点的子树(同样,按照相同的规则)。
此编码可以转换为二叉树,如下所示:
function makeBinaryTree(input):
i = 0 # character index in input
function recur():
if i >= input.length or input[i] == ")":
i = i + 1
return NIL
i = i + 1
node = new Node
node.left = recur()
if i >= input.length or input[i] == ")":
i = i + 1
return node
node.right = recur()
return node
return recur()
这是JavaScript中的一个实现,它对那些4节点树进行转换,并漂亮地打印出结果树:
function makeBinaryTree(input) {
let i = 0; // character index in input
return recur();
function recur() {
if (i >= input.length || input[i++] === ")") return null;
let node = { left: recur(), right: null };
if (i >= input.length || input[i] === ")") {
i++;
return node;
}
node.right = recur();
return node;
}
}
// Helper function to pretty print a tree
const disc = "\u2B24";
function treeAsLines(node) {
let left = [""], right = [""];
if (node.left) left = treeAsLines(node.left);
if (node.right) right = treeAsLines(node.right);
while (left.length < right.length) left.push(" ".repeat(left[0].length));
while (left.length > right.length) right.push(" ".repeat(left[0].length));
let topLeft = "", topRight = "";
let i = left[0].indexOf(disc);
if (i > -1) topLeft = "┌".padEnd(left[0].length-i+1, "─");
i = right[0].indexOf(disc);
if (i > -1) topRight = "┐".padStart(i+2, "─");
return [topLeft.padStart(left[0].length+1) + disc + topRight.padEnd(right[0].length+1)]
.concat(left.map((line, i) => line + " " + right[i]));
}
// The trees as listed in Table 1 of http://www.cs.utsa.edu/~wagner/knuth/fasc4a.pdf
let inputs = [
"()()()()",
"()()(())",
"()(())()",
"()(()())",
"()((()))",
"(())()()",
"(())(())",
"(()())()",
"(()()())",
"(()(()))",
"((()))()",
"((())())",
"((()()))",
"(((())))"
];
for (let input of inputs) {
let tree = makeBinaryTree(input);
console.log(input);
console.log(treeAsLines(tree).join("\n"));
}
答案 1 :(得分:1)
如果我正确理解Knuth,则表示形式如下:一对匹配的括号表示一个节点,例如()= A.连续两对匹配的括号表示第二个节点是第一个的右子节点,例如()()= A->B。两对嵌入括号表示内部节点是外部节点的左子节点,即(())= B <-A。因此,()()()() = A-> B-> C-> D。
将括号转换为二叉树的可能算法是:
convert(parentheses):
if parentheses is empty:
return Nil
root = Node()
left_start = 1
left_end = Nil
open = 0
for p = 0 to |parentheses|-1:
if parentheses[p] == '(':
open += 1
else
open -= 1
if open == 0:
left_end = p
break
root.left = convert(parentheses[left_start:left_end] or empty if index out of bound)
root.right = convert(parentheses[left_end+1:] or empty if index out of bound)
return root
它通过递归转换二进制树L <-A-> R中的括号(L)R来工作。