C++二叉树操作方法及程序输入元素后崩溃原因排查
嘿,我来帮你搞定这两个二叉树相关的问题!
操作二叉树核心就是围绕节点定义和基础操作展开,我给你拆解成几个关键步骤:
定义二叉树节点:一般用结构体或者类来实现,一定要记得初始化左右指针为
nullptr,不然野指针会给你挖无数坑。比如:struct TreeNode { int val; TreeNode* left; TreeNode* right; // 用构造函数自动初始化指针 TreeNode(int value) : val(value), left(nullptr), right(nullptr) {} };插入节点:常用递归或迭代两种方式,递归写法更简洁。比如写一个插入函数,根据值的大小判断往左还是往右子树插:
// 用指针引用确保修改能作用到原节点 void insert(TreeNode*& root, int val) { if (root == nullptr) { root = new TreeNode(val); return; } if (val < root->val) { insert(root->left, val); } else { insert(root->right, val); } }遍历节点:分为前序、中序、后序(递归/迭代实现),还有层序遍历(用队列实现)。比如中序递归遍历:
void inorderTraversal(TreeNode* root) { if (root == nullptr) return; inorderTraversal(root->left); cout << root->val << " "; inorderTraversal(root->right); }其他常用操作:比如查找节点(和插入逻辑类似)、删除节点(相对复杂,要处理叶子节点、单孩子节点、双孩子节点三种情况),还有销毁树释放内存(避免内存泄漏)。
结合你描述的情况(结构体含两个指针+根节点,用add函数插入n个元素后崩溃),大概率是这几个常见坑:
野指针未初始化:如果你的结构体没有给左右指针赋初始值
nullptr,创建节点后left/right会是随机的野指针。当add函数判断节点是否为空时,野指针可能被误判为非空,进而访问它的成员,直接触发内存访问错误崩溃。一定要在结构体构造函数里初始化指针!add函数的逻辑错误:最常见的是形参指针未传递修改。比如你写的add函数是这样的:void add(TreeNode* root, int val) { if (root == nullptr) { root = new TreeNode(val); // 这里只修改了局部形参,原根节点还是nullptr! return; } // ... 其他逻辑 }这种情况下,根节点始终是
nullptr,后续操作必然访问空指针崩溃。解决办法是用指针的引用(TreeNode*& root)或者让函数返回新的节点指针。输入处理异常:如果读取节点个数
br时,输入的不是整数,cin会进入失败状态,导致br变成垃圾值(比如极大的数),循环插入大量节点要么栈溢出(递归插入的话),要么内存耗尽崩溃。可以在输入后加个判断:if (!(cin >> br)) { cout << "输入无效,请输入整数!" << endl; return 1; }递归栈溢出:如果输入的元素是有序的(比如从小到大),二叉树会退化成链表,递归插入的深度等于节点数
n。如果n很大(比如上万),栈空间会被耗尽,直接触发崩溃。这种情况可以改成迭代的插入方式。
给你一个能正常运行的简化示例代码,对比看看你的程序哪里不一样:
#include "stdafx.h" #include <iostream> using namespace std; struct TreeNode { int val; TreeNode* left; TreeNode* right; TreeNode(int value) : val(value), left(nullptr), right(nullptr) {} }; void add(TreeNode*& root, int val) { if (root == nullptr) { root = new TreeNode(val); return; } if (val < root->val) { add(root->left, val); } else { add(root->right, val); } } void inorderTraversal(TreeNode* root) { if (root == nullptr) return; inorderTraversal(root->left); cout << root->val << " "; inorderTraversal(root->right); } int main() { int br; cout << "请输入节点个数:"; if (!(cin >> br)) { cout << "输入错误!" << endl; return 1; } TreeNode* root = nullptr; cout << "请输入" << br << "个节点值:"; for (int i = 0; i < br; ++i) { int val; cin >> val; add(root, val); } // 测试遍历 cout << "中序遍历结果:"; inorderTraversal(root); cout << endl; // 记得释放内存(这里省略,实际项目要写销毁函数) return 0; }
内容的提问来源于stack exchange,提问作者A.Antonov

