C++学习——二叉搜索树(一)


前言

本文为《C++学习》的第9篇文章,今天学习二叉搜索树。


一、二叉搜索树的模板代码

#include<iostream>
using namespace std;

/**
 * @brief 二叉搜索树节点模板结构体
 * @tparam T 节点存储数据类型
 * @note 左子树所有节点值小于当前节点,右子树所有节点值大于当前节点[7,8](@ref)
 */
template<typename T>
struct TreeNode {
    T val;            ///< 节点存储值
    TreeNode *left;   ///< 左子树指针
    TreeNode *right;  ///< 右子树指针
    
    /// 默认构造函数初始化空节点
    TreeNode() : val(0), left(nullptr), right(nullptr) {}
    
    /// 带值构造函数初始化叶子节点
    TreeNode(T x) : val(x), left(nullptr), right(nullptr) {}
};

/**
 * @brief 二叉搜索树模板类
 * @tparam T 树节点存储数据类型
 * @note 支持插入、删除、搜索和中序遍历操作,时间复杂度平均O(log n)[7](@ref)
 */
template<typename T>
class BinarySearchTree {
private: 
    TreeNode<T> *root; ///< 树根节点指针
    
    // 核心递归辅助函数组(内部使用)
    TreeNode<T>* insertNode(TreeNode<T> *node, T value);
    TreeNode<T>* removeNode(TreeNode<T> *node, T value);
    bool searchNode(TreeNode<T> *node, T value);
    void inOrder(TreeNode<T> *node);
    void destroyTree(TreeNode<T>* node);

public:
    /// 构造函数初始化空树
    BinarySearchTree() : root(nullptr) {}                
    
    /// 析构函数通过后序遍历释放所有节点内存[2,5](@ref)
    ~BinarySearchTree() { destroyTree(root); }

    /**
     * @brief 插入新节点
     * @param value 待插入值
     * @note 若值已存在则保留原树结构[4](@ref)
     */
    void insert(T value) { root = insertNode(root, value); }
    
    /**
     * @brief 删除指定值节点
     * @param value 待删除值
     * @note 处理三种情况:无子节点/单子节点/双子节点[3,8](@ref)
     */
    void remove(T value) { root = removeNode(root, value); }
    
    /**
     * @brief 搜索指定值存在性
     * @param value 查询目标值
     * @return 存在返回true,否则false
     */
    bool search(T value) { return searchNode(root, value); }
    
    /// 中序遍历打印有序序列[5,7](@ref)
    void inOrderTraversal() { inOrder(root); cout << endl; }
};

/* 递归销毁树(后序遍历)*/
template<typename T>
void BinarySearchTree<T>::destroyTree(TreeNode<T>* node) {
    if(node) {
        destroyTree(node->left);  // 递归删除左子树
        destroyTree(node->right); // 递归删除右子树
        delete node;              // 释放当前节点内存
    }
}

/* 插入节点(递归实现)
   @param node 当前子树根节点
   @param value 待插入值
   @return 插入后的子树根节点 */
template<typename T>
TreeNode<T>* BinarySearchTree<T>::insertNode(TreeNode<T>* node, T value) {
    if(node == nullptr) { 
        return new TreeNode<T>(value);
    }
    if(value < node->val) {          
        node->left = insertNode(node->left, value);
    } else if(value > node->val) {  
        node->right = insertNode(node->right, value);
    }
    return node; // 值相等时不插入[2](@ref)
}

/* 删除节点(递归实现)
   @param node 当前子树根节点
   @param value 待删除值
   @return 删除后的子树根节点 */
template<typename T>
TreeNode<T>* BinarySearchTree<T>::removeNode(TreeNode<T>* node, T value) {
    if(node == nullptr) return nullptr;
    
    // 递归查找目标节点
    if(value < node->val) {          
        node->left = removeNode(node->left, value);
    } else if(value > node->val) {  
        node->right = removeNode(node->right, value);
    } else { // 找到目标节点
        // Case 1: 无子节点
        if(node->left == nullptr && node->right == nullptr) {
            delete node;
            return nullptr;
        }
        // Case 2: 单子节点
        else if(node->left == nullptr) {
            TreeNode<T>* temp = node->right;
            delete node;
            return temp;
        } else if(node->right == nullptr) {
            TreeNode<T>* temp = node->left;
            delete node;
            return temp;
        }
        // Case 3: 双子节点(寻找右子树最小节点替换)[2,7](@ref)
        else {
            TreeNode<T>* successor = node->right;
            while(successor->left != nullptr)
                successor = successor->left;
            node->val = successor->val; // 替换值
            node->right = removeNode(node->right, successor->val); // 递归删除替换节点
        }
    }
    return node;
}

/* 搜索节点(递归实现)
   @param node 当前子树根节点
   @param value 目标值
   @return 是否存在目标值 */
template<typename T>
bool BinarySearchTree<T>::searchNode(TreeNode<T>* node, T value) {
    if(node == nullptr) return false;
    if(value < node->val) {          
        return searchNode(node->left, value);
    } else if(value > node->val) {  
        return searchNode(node->right, value);
    } else {
        return true; // 找到目标值
    }
}

/* 中序遍历(递归实现)*/
template<typename T>
void BinarySearchTree<T>::inOrder(TreeNode<T>* node) {
    if(node) {
        inOrder(node->left);
        cout << node->val << " ";
        inOrder(node->right);
    }
}

int main() {
    BinarySearchTree<int> bst;
    
    // 测试插入(生成链表结构)
    bst.insert(10);
    bst.insert(20);
    bst.insert(30);
    bst.insert(40);
    bst.insert(50);
    bst.insert(60);
    bst.insert(70);
    bst.insert(80);
    bst.insert(90);
    bst.insert(100);
    bst.insert(110);
    
    // 验证中序遍历有序性
    bst.inOrderTraversal(); // 输出:10 20 30 40 50 60 70 80 90 100 110 
    
    // 验证搜索功能
    cout << boolalpha;
    cout << bst.search(10) << endl;  // true
    cout << bst.search(120) << endl; // false
    
    // 测试删除叶子节点
    bst.remove(110);
    bst.inOrderTraversal(); // 输出:10 20 30 40 50 60 70 80 90 100 
    
    return 0;
}

这就是今天的全部内容了,谢谢大家的观看,不要忘了给一个免费的赞哦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mentality瑞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值