C++二叉树节点应定义为struct,含int val及初始化为nullptr的left、right指针,并提供无参、单参、三参构造函数;前序/中序/后序递归遍历均需先判空,仅处理顺序不同;非递归遍历用stack模拟,中序需持续向左入栈再弹出转向右;建树时禁用局部变量地址,须用new或智能指针确保生命周期安全。
直接用 struct 最简洁,关键是要默认初始化指针为 nullptr,避免野指针;同时加一个带参构造函数,方便快速创建节点。
val 存数据,类型按需改(比如 int 或 string)left 和 right 必须初始化为 nullptr,否则递归遍历时可能崩溃new 分配子节点且需要手动释放(一般推荐栈上创建或智能指针)struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode* l, TreeNode* r) : val(x), left(l), right(r) {}
};三者结构完全一致:都是“访问当前 → 递归左 → 递归右”,区别只在打印/处理 root->val 的位置。记住口诀:“前根左右、中左根右、后左右根”。
root → traverse(root->left) → traverse(root->right)
root → 递归右(BST 中序即升序)root(适合删树、求高度等依赖子树结果的场景)if (!root) return;,否则访问 nullptr->val 直接段错误void preorder(TreeNode* root) {
if (!root) return;
cout << root->val << " "; // 前序:根最先
preorder(root->left);
preorder(root->right);
}递归本质是系统用栈保存现场,自己模拟时核心是「什么时候 push、什么时候 pop、什么时候记录结果」。前序最简单,中序次之,后序最难——别硬记,用「标记法」统一处理。
false 标记(表示未处理子树),第二次带 true(可输出)。遇到 true 才记录值stack 不够,得用 stack> 或自定义结构体// 中序非递归示例
void inorder_iterative(TreeNode* root) {
stack st;
TreeNode* cur = root;
while (cur || !st.empty()) {
while (cur) {
st.push(cur);
cur = cur->left; // 一直压左
}
cur = st.top(); st.pop();
cout << cur->val << " "; // 此时左子树已完,访问根
cur = cur->right; // 转向右
}
} 新手常在构建测试树时崩溃,根本原因不是遍历逻辑错,而是节点指针没连对,或者连了局部变量地址。
TreeNode node(1); TreeNode* root = &node; —— node 是栈变量,函数返回后地址失效new(记得 delete)或更推荐用智能指针 unique_ptr
root->left = ... 或写成 root->left->left = ...(中间
nullptr 时解引用必崩)assert(root != nullptr);,或用 if (!root) { cout
后序遍历的左右子树依赖性最强,一旦某个 left 或 right 是悬空指针,它会第一个暴露问题。