文章目录
前言
本文为《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;
}
这就是今天的全部内容了,谢谢大家的观看,不要忘了给一个免费的赞哦!