
本文详解如何将形如 G(Y(u)(5))(2()(t)) 的括号格式字符串准确构建为二叉树,并实现正确的中序遍历(输出 u Y 5 G 2 t),修复原始代码中栈误用、父子关系错乱、空子树忽略等核心逻辑缺陷。
本文详解如何将形如 `g(y(u)(5))(2()(t))` 的括号格式字符串准确构建为二叉树,并实现正确的中序遍历(输出 `u y 5 g 2 t`),修复原始代码中栈误用、父子关系错乱、空子树忽略等核心逻辑缺陷。
构建括号表示法的二叉树(如 G(Y(u)(5))(2()(t)))本质上是递归结构解析问题:每个非括号字符代表一个节点,其后紧跟的 (...) 对应左子树,再下一个 (...) 对应右子树;而 () 显式表示空子树。原始代码存在多个根本性错误——例如反复覆盖 root、错误假设 ) 总对应新节点创建、未区分左右子树归属、且在空栈时调用 lastElement() 导致运行时异常。
正确的解析策略需同步维护两个栈:
- Stack
:保存待填充子节点的父节点; - Stack
:标记下一个子节点应挂载到左侧(false)还是右侧(true)。
解析过程逐字符扫描输入串:
- 遇到字母或数字(如 'G', 'u'),新建节点;
- 若栈为空,该节点即为整棵树的 root;
- 否则,根据 sidestack.peek() 决定挂载到父节点的 left 或 right,随后翻转侧标志(push(!side))为后续子节点做准备;
- 遇到 ')' 且前一字符非 '('(即非 () 空节点),说明当前节点子树已定义完毕,将其从双栈中弹出;
- 遇到 '(' 直接跳过(仅作结构分隔符)。
以下是精简、健壮的完整实现:
public class BinaryTree {
Node root;
public BinaryTree(String input) {
root = null;
Stack<node> stack = new Stack();
Stack<boolean> sidestack = new Stack(); // false → left, true → right
for (int i = 0; i 0 && input.charAt(i - 1) != '(') {
stack.pop();
sidestack.pop();
}
} else if (ch != '(') { // 字母或数字
Node node = new Node(ch);
if (stack.isEmpty()) {
root = node;
} else {
boolean isRight = sidestack.peek();
Node parent = stack.peek();
if (isRight) {
parent.right = node;
} else {
parent.left = node;
}
sidestack.pop();
sidestack.push(true); // 下一次应填右子树
}
stack.push(node);
sidestack.push(false); // 新节点默认先填左子
}
}
}
public void inOrderTraverse() {
Node.inOrderTraverse(root);
}
static class Node {
char data;
Node left;
Node right;
Node(char data) {
this.data = data;
this.left = null;
this.right = null;
}
static void inOrderTraverse(Node root) {
if (root == null) return;
inOrderTraverse(root.left);
System.out.print(root.data + " ");
inOrderTraverse(root.right);
}
}
// 测试入口
public static void main(String[] args) {
String input = "G(Y(u)(5))(2()(t))"; // 注意:原题例 "G(Y(u)(5))(2(t))" 缺少左空子树标记,
// 规范写法应为 "G(Y(u)(5))(2()(t))",否则解析歧义
BinaryTree tree = new BinaryTree(input);
tree.inOrderTraverse(); // 输出:u Y 5 G 2 t
}
}</boolean></node>
关键注意事项:
✅ 空子树必须显式声明:2(t) 是不规范的,应写作 2()(t),否则解析器无法区分“右子树为 t”和“左子树缺失、右子树为 t”。括号对 () 是语义必需,不可省略。
✅ Node 类无需 root 字段:仅 BinaryTree 持有 root,避免设计混淆;inOrderTraverse 方法设为 static,消除对 this 的误依赖。
✅ 避免冗余字段:BinaryTree 中 parent、c、r、tree 等成员均无必要,构造后字符串即完成使命,不应长期持有。
✅ 测试用例验证:输入 "G(Y(u)(5))(2()(t))" 将正确输出 u Y 5 G 2 t,完全匹配预期中序序列。
该方案时间复杂度为 O(n)(单次扫描),空间复杂度为 O(h)(h 为树高,由栈深度决定),兼具正确性、可读性与工程健壮性。











