一、简介和应用 二叉搜索树(Binary Search Tree, BST)是一种特殊的二叉树数据结构,其中每个节点的值大于其左子树所有节点的值,小于其右子树所有节点的值。这种特性使得BST在查找、插入和删除操作上具有很高的效率。 应用场景: 文件系统目录管理 字典和电话簿实现 游戏中的高分排行榜 网络路由表 内存分配管理
BST的平均时间复杂度为O(log n),在数据有序性要求高且需要频繁查找的场景中表现优异。 二、注意事项重复值:标准BST不支持重复值(需要特殊处理) 删除策略:删除节点有多种情况需要考虑
三、实现步骤解析定义节点结构:创建包含数据、左 指针和右指针的结构体 初始化BST:创建根节点并维护节点计数器 实现核心操作:
辅助功能:
查找前驱节点:用于删除操作 查找最小值:用于删除双子节点情况
实现遍历:
四、完整代码和注释- #include<iostream>
- using namespACe std;
- // 定义二叉搜索树节点结构
- struct treenode{
- int data=0; // 节点存储的数据,默认为0
- treenode* left=nullptr; // 左子节点指针,默认为空
- treenode* right=nullptr; // 右子节点指针,默认为空
- };
- // 定义二叉搜索树类
- class binaryfindtree{
- treenode* root=new treenode; // 根节点
- int sum = 0; // 节点计数器
-
- // 内部递归插入方法
- void add(int data, treenode* root){
- if (sum==0){ // 如果是第一个节点
- root->data = data; // 直接赋值给根节点
- }else{
- if(data<root->data){ // 如果数据小于当前节点
- if(root->left) // 如果左子节点存在
- add(data, root->left); // 递归向左子树插入
- else { // 如果左子节点不存在
- root->left = new treenode; // 创建新节点
- root->left->data = data; // 赋值
- }
- }else{ // 如果数据大于等于当前节点
- if(root->right) // 如果右子节点存在
- add(data, root->right); // 递归向右子树插入
- else { // 如果右子节点不存在
- root->right = new treenode; // 创建新节点
- root->right->data = data; // 赋值
- }
- }
- }
- sum++; // 节点计数增加
- }
-
- // 内部递归查找方法
- treenode* get(int data, treenode* root){
- if (!root) // 如果节点为空
- return nullptr; // 返回空指针
- if (root->data == data) // 如果找到数据
- return root; // 返回当前节点
- if (data < root->data) // 如果数据小于当前节点
- return get(data, root->left); // 递归左子树查找
- else // 如果数据大于当前节点
- return get(data, root->right); // 递归右子树查找
- }
-
- // 查找指定节点的父节点
- treenode* getpre(int data, treenode* root) {
- if (!root) // 如果节点为空
- return nullptr; // 返回空指针
- if (!root->left and !root->right) // 如果是叶子节点
- return nullptr; // 返回空指针
-
- // 检查左子节点
- if (!root->left){ // 如果没有左子节点
- if (root->right->data == data) // 如果右子节点匹配
- return root; // 返回当前节点(父节点)
- }else{
- if (!root->right){ // 如果没有右子节点
- if (root->left->data == data) // 如果左子节点匹配
- return root; // 返回当前节点(父节点)
- }else{ // 如果有两个子节点
- if (root->left->data == data or root->right->data == data) // 如果任一子节点匹配
- return root; // 返回当前节点(父节点)
- }
- }
-
- // 递归查找左右子树
- if (getpre(data, root->left)) // 先在左子树查找
- return getpre(data, root->left);
- else // 再在右子树查找
- return getpre(data, root->right);
- }
-
- // 查找子树中的最小节点
- treenode* mindata(treenode* root) {
- if (!root->left) // 如果没有左子节点
- return root; // 当前节点就是最小节点
- return mindata(root->left); // 递归查找左子树
- }
-
- // 内部递归删除方法
- treenode* del(int data, treenode* root){
- if (!root or (!root->left and !root->right)) // 空树或只有根节点
- return nullptr;
-
- treenode* tmp = get(data, root); // 找到要删除的节点
- treenode* pre = getpre(data, root); // 找到父节点
- bool lr = pre->right == tmp; // 判断是左子节点还是右子节点
-
- // 情况1: 要删除的节点是叶子节点
- if (!tmp->left and !tmp->right){
- !lr ? pre->left = nullptr : pre->right = nullptr; // 父节点对应指针置空
- return root;
- }
-
- // 情况2: 要删除的节点只有一个子节点
- if (!tmp->right) // 只有左子节点
- !lr ? pre->left = tmp->left : pre->right = tmp->left; // 用左子节点替代
- else{
- if (!tmp->left) // 只有右子节点
- !lr ? pre->left = tmp->right : pre->right = tmp->right; // 用右子节点替代
- else{ // 情况3: 有两个子节点
- tmp->data = mindata(root->right)->data; // 用右子树最小节点值替换
- tmp->right = del(tmp->data, mindata(root->right)); // 删除右子树最小节点
- }
- }
- sum--; // 节点计数减少
- return root;
- }
-
- // 前序遍历(根-左-右)
- void preorder(treenode* root)
- {
- if (!root) // 如果节点为空
- return; // 返回
- cout << root->data << " "; // 先访问根节点
- preorder(root->left); // 再遍历左子树
- preorder(root->right); // 最后遍历右子树
- }
-
- // 中序遍历(左-根-右)
- void inorder(treenode* root){
- if (!root) // 如果节点为空
- return; // 返回
- inorder(root->left); // 先遍历左子树
- cout << root->data << " "; // 再访问根节点
- inorder(root->right); // 最后遍历右子树
- }
-
- public:
- // 公开插入接口
- void add(int data){
- add(data, root);
- }
-
- // 查找接口
- bool find(int data){
- return get(data, root) != nullptr; // 转换为bool值返回
- }
-
- // 删除接口
- void del(int data){
- root = del(data, root);
- }
-
- // 中序遍历接口
- void inorder(){
- inorder(root);
- cout << endl;
- }
-
- // 前序遍历接口
- void preorder()
- {
- preorder(root);
- cout << endl;
- }
- };
复制代码 来源:大矩学习资料
|