You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 19:06:04