
👨💻 关于作者:会编程的土豆
"不是因为看见希望才坚持,而是坚持了才看见希望。"
你好,我是会编程的土豆,一名热爱后端技术的Java学习者。
📚 正在更新中的专栏:
-
《数据结构与算法》😊😊😊
-
《leetcode hot 100》🥰🥰🥰🤩🤩🤩
-
《数据库mysql》
💕作者简介:后端学习者
1.

cpp
#include <iostream>
#include <cstring>
using namespace std;
struct Node {
char left, right;
} tree[130]; // 用ASCII码作为索引
string preorder;
void preOrder(char root) {
if (root == '*') return; // 空节点
preorder += root; // 访问根节点
preOrder(tree[root].left); // 遍历左子树
preOrder(tree[root].right); // 遍历右子树
}
int main() {
int n;
cin >> n;
char root; // 记录根节点
bool isFirst = true;
for (int i = 0; i < n; i++) {
string s;
cin >> s;
char node = s[0];
if (isFirst) {
root = node; // 第一行的节点是根节点
isFirst = false;
}
tree[node].left = s[1];
tree[node].right = s[2];
}
preOrder(root);
cout << preorder << endl;
return 0;
}
从输入构建二叉树并输出前序遍历:一篇彻底讲清楚(数组建树法)
这类题在数据结构中非常经典:
给你一组节点信息(父节点 + 左右孩子),让你构建二叉树并进行遍历
你这段代码已经是竞赛级标准写法,但很多人写完其实并不理解"为什么这样就能建树"。
这篇文章就帮你把这个过程彻底讲透。
一、题目本质
输入类似:
3
ABC
B*D
C**
含义是:
A 的左孩子是 B,右孩子是 C
B 的左孩子是 *(空),右孩子是 D
C 没有孩子
二、核心思想
一句话总结:
用数组模拟"指针",用字符直接当下标建树
三、数据结构设计
struct Node {
char left, right;
} tree[130];
为什么用 130?
ASCII 字符范围足够(A~Z)
关键理解
tree['A'] 就表示 A 这个节点
例如:
tree['A'].left = 'B';
tree['A'].right = 'C';
就等价于:
A
├── B
└── C
四、建树过程(重点)
for (int i = 0; i < n; i++) {
string s;
cin >> s;
char node = s[0];
tree[node].left = s[1];
tree[node].right = s[2];
}
输入解析
例如:
ABC
表示:
A.left = B
A.right = C
特殊符号
* 表示空节点
五、根节点怎么确定?
if (isFirst) {
root = node;
}
为什么第一行是根?
因为题目保证输入顺序:
第一行就是整棵树的根
(这是这类题的默认规则)
六、前序遍历函数(核心)
void preOrder(char root) {
if (root == '*') return;
preorder += root;
preOrder(tree[root].left);
preOrder(tree[root].right);
}
逻辑解释
前序遍历 = 根 → 左 → 右
执行顺序:
1. 访问当前节点
2. 递归左子树
3. 递归右子树
七、执行流程示例
输入:
3
ABC
B*D
C**
构建树
A
/ \
B C
\
D
遍历过程
访问 A
→ 访问 B
→ 访问 D
→ 返回
→ 访问 C
输出结果
ABDC
八、为什么不用指针也能建树?
很多人卡在这里。
本质原因
字符本身就是"节点编号"
所以:
tree['A'] → 就是 A 节点
不需要:
new TreeNode
对比指针写法
| 方法 | 特点 |
|---|---|
| 指针建树 | 面向对象 |
| 数组建树 | 竞赛更快 |
九、时间复杂度
建树:O(n)
遍历:O(n)
总:O(n)
十、空间复杂度
O(n)
十一、常见错误
1. 忘记判断 '*'
if (root == '*') return;
2. 根节点写错
不是随便选的,是:
第一行输入
3. 数组越界
tree[130] 是安全范围
十二、扩展:三种遍历对比
| 遍历方式 | 顺序 |
|---|---|
| 前序 | 根 → 左 → 右 |
| 中序 | 左 → 根 → 右 |
| 后序 | 左 → 右 → 根 |
改成中序
preOrder(tree[root].left);
preorder += root;
preOrder(tree[root].right);
改成后序
preOrder(tree[root].left);
preOrder(tree[root].right);
preorder += root;
十三、一句话总结
数组建树 = 用字符当下标 + 直接记录左右孩子 + 递归遍历