C++实现二叉树类时AddNode报错root为NULL且析构不生效问题
C++二叉树类问题修复方案
问题1:AddNode无法填充节点,root始终为NULL
根因
AddNode的src参数为按值传递的指针,函数内部修改src = n仅对局部副本生效,不会修改类成员root本身- 插入根节点(
parent == NULL的场景)时,没有主动对root赋值,导致root一直保持初始化的NULL状态
问题2:析构函数无法触发、内存无法释放
根因
Node析构函数中调用Destroy,而Destroy内部执行delete this,会再次触发Node析构函数,造成无限递归崩溃,释放逻辑完全无法正常执行Tree析构函数未判断root是否为空,当树未插入节点时直接调用root->Destroy()会触发空指针访问崩溃- 额外问题:
Search函数存在两处逻辑错误:- 遍历方向写反:当前节点值小于目标值时应该向右子树遍历,原代码向左遍历,永远找不到大于根节点的元素
- 指针修改后未判空就访问成员,遍历到NULL时会直接崩溃
修复后的完整代码
#include <iostream> #include <string> class Node { public: Node() { std::cout << "Node Constructor\n"; left = NULL; right = NULL; parent = NULL; }; virtual ~Node() { std::cout << "Node Destructor\n"; }; void SetEngWord(std::string eng) { engWord = eng; } void SetRusWord(std::string rus) { rusWord = rus; } std::string GetEngWord() { return engWord; } std::string GetRusWord() { return rusWord; } Node* GetLeft() { return left; } Node* GetRight() { return right; } Node* GetParent() { return parent; } void SetLeft(Node* l) { left = l; } void SetRight(Node* r) { right = r; } void SetParent(Node* p) { parent = p; } void PrintWord() { std::cout << engWord << " - " << rusWord << std::endl; } void Destroy(); private: std::string engWord; std::string rusWord; Node* left; Node* right; Node* parent; }; void Node::Destroy() { if (left != NULL) { left->Destroy(); delete left; left = NULL; } if (right != NULL) { right->Destroy(); delete right; right = NULL; } // 移除delete this,避免重复析构 } class Tree { public: Tree() { std::cout << "Tree Constructor\n"; root = NULL; }; virtual ~Tree() { std::cout << "Tree Destructor\n"; if (root != NULL) { // 新增空指针判断 root->Destroy(); delete root; root = NULL; } }; void Add(std::string eng, std::string rus); void AddNode(Node* src, Node* parent, Node* n, bool left); Node* Search(std::string s); private: Node* root; }; void Tree::Add(std::string eng, std::string rus) { Node* n = new Node; n->SetEngWord(eng); n->SetRusWord(rus); AddNode(root,NULL,n,true); } void Tree::AddNode(Node* src, Node* parent, Node* n, bool left) { if (src == NULL) { // 新增根节点赋值逻辑 if (parent == NULL) { root = n; } else { n->SetParent(parent); if (left) { parent->SetLeft(n); } else { parent->SetRight(n); } } return; } if (n->GetEngWord() < src->GetEngWord()) { AddNode(src->GetLeft(), src, n, true); } else { AddNode(src->GetRight(), src, n, false); } } Node* Tree::Search(std::string s) { Node* n = root; while(n != NULL) { if (n->GetEngWord() == s) { return n; } else if (n->GetEngWord() < s) { n = n->GetRight(); // 修正遍历方向,小于目标值向右走 } else { n = n->GetLeft(); } } return NULL; } int main() { Tree tree; tree.Add("a","aa"); tree.Add("b","bb"); tree.Add("c","cc"); Node* n = tree.Search("b"); if (n != NULL) n->PrintWord(); else std::cout << "NULL" << std::endl; return 0; }
修复后运行效果
可以正常打印b - bb,所有节点的构造、析构函数都会正常触发,无内存泄漏、无崩溃问题。
内容的提问来源于stack exchange,提问作者user9543846
相关产品推荐
相关产品推荐

