查看: 37|回复: 0

二叉搜索树入门指南:高效查找的数据结构实现

[复制链接]
  • TA的每日心情
    擦汗
    10 小时前
  • 签到天数: 37 天

    [LV.5]常住居民I

    36

    主题

    0

    回帖

    67

    积分

    注册会员

    Rank: 2

    积分
    67
    发表于 2025-6-29 09:36:37 | 显示全部楼层 |阅读模式
    一、简介和应用

    二叉搜索树(Binary Search Tree, BST)是一种特殊的二叉树数据结构,其中每个节点的值大于其左子树所有节点的值,小于其右子树所有节点的值。这种特性使得BST在查找、插入和删除操作上具有很高的效率。

    ‌应用场景‌:

    • 数据库索引实现
    • 文件系统目录管理
    • 字典和电话簿实现
    • 游戏中的高分排行榜
    • 网络路由表
    • 内存分配管理

    BST的平均时间复杂度为O(log n),在数据有序性要求高且需要频繁查找的场景中表现优异。

    二、注意事项
    • 平衡问题:不平衡的BST会退化为链表,效率降低
    • 重复值:标准BST不支持重复值(需要特殊处理)
    • 删除策略:删除节点有多种情况需要考虑
    • 内存管理:需要手动释放删除的节点
    • 递归深度:大量数据可能导致溢出

    三、实现步骤解析
    • ‌定义节点结构‌:创建包含数据、左指针和右指针的结构体
    • ‌初始化BST‌:创建根节点并维护节点计数器
    • ‌实现核心操作‌:

      • 插入节点:递归找到合适位置插入新节点
      • 查找节点:利用BST特性快速定位
      • 删除节点:处理三种情况(无子节点、单子节点、双子节点)

    • ‌辅助功能‌:

      • 查找前驱节点:用于删除操作
      • 查找最小值:用于删除双子节点情况

    • ‌实现遍历‌:

      • 前序遍历:根-左-右顺序
      • 中序遍历:左-根-右顺序(得到有序序列)

    四、完整代码和注释
    1. #include<iostream>
    2. using namespACe std;

    3. // 定义二叉搜索树节点结构
    4. struct treenode{
    5.     int data=0;            // 节点存储的数据,默认为0
    6.     treenode* left=nullptr;  // 左子节点指针,默认为空
    7.     treenode* right=nullptr; // 右子节点指针,默认为空
    8. };

    9. // 定义二叉搜索树类
    10. class binaryfindtree{
    11.     treenode* root=new treenode; // 根节点
    12.     int sum = 0;                 // 节点计数器
    13.    
    14.     // 内部递归插入方法
    15.     void add(int data, treenode* root){
    16.         if (sum==0){             // 如果是第一个节点
    17.             root->data = data;   // 直接赋值给根节点
    18.         }else{
    19.             if(data<root->data){ // 如果数据小于当前节点
    20.                 if(root->left)   // 如果左子节点存在
    21.                     add(data, root->left); // 递归向左子树插入
    22.                 else {           // 如果左子节点不存在
    23.                     root->left = new treenode; // 创建新节点
    24.                     root->left->data = data;   // 赋值
    25.                 }
    26.             }else{               // 如果数据大于等于当前节点
    27.                 if(root->right)  // 如果右子节点存在
    28.                     add(data, root->right); // 递归向右子树插入
    29.                 else {           // 如果右子节点不存在
    30.                     root->right = new treenode; // 创建新节点
    31.                     root->right->data = data;   // 赋值
    32.                 }
    33.             }
    34.         }
    35.         sum++; // 节点计数增加
    36.     }
    37.    
    38.     // 内部递归查找方法
    39.     treenode* get(int data, treenode* root){
    40.         if (!root)              // 如果节点为空
    41.             return nullptr;      // 返回空指针
    42.         if (root->data == data) // 如果找到数据
    43.             return root;         // 返回当前节点
    44.         if (data < root->data)  // 如果数据小于当前节点
    45.             return get(data, root->left); // 递归左子树查找
    46.         else                    // 如果数据大于当前节点
    47.             return get(data, root->right); // 递归右子树查找
    48.     }
    49.    
    50.     // 查找指定节点的父节点
    51.     treenode* getpre(int data, treenode* root) {
    52.         if (!root)              // 如果节点为空
    53.             return nullptr;      // 返回空指针
    54.         if (!root->left and !root->right) // 如果是叶子节点
    55.             return nullptr;      // 返回空指针
    56.             
    57.         // 检查左子节点
    58.         if (!root->left){       // 如果没有左子节点
    59.             if (root->right->data == data) // 如果右子节点匹配
    60.                 return root;     // 返回当前节点(父节点)
    61.         }else{
    62.             if (!root->right){  // 如果没有右子节点
    63.                 if (root->left->data == data) // 如果左子节点匹配
    64.                     return root; // 返回当前节点(父节点)
    65.             }else{              // 如果有两个子节点
    66.                 if (root->left->data == data or root->right->data == data) // 如果任一子节点匹配
    67.                     return root; // 返回当前节点(父节点)
    68.             }
    69.         }
    70.         
    71.         // 递归查找左右子树
    72.         if (getpre(data, root->left)) // 先在左子树查找
    73.             return getpre(data, root->left);
    74.         else                         // 再在右子树查找
    75.             return getpre(data, root->right);
    76.     }
    77.    
    78.     // 查找子树中的最小节点
    79.     treenode* mindata(treenode* root) {
    80.         if (!root->left)       // 如果没有左子节点
    81.             return root;        // 当前节点就是最小节点
    82.         return mindata(root->left); // 递归查找左子树
    83.     }
    84.    
    85.     // 内部递归删除方法
    86.     treenode* del(int data, treenode* root){
    87.         if (!root or (!root->left and !root->right)) // 空树或只有根节点
    88.             return nullptr;
    89.             
    90.         treenode* tmp = get(data, root); // 找到要删除的节点
    91.         treenode* pre = getpre(data, root); // 找到父节点
    92.         bool lr = pre->right == tmp;     // 判断是左子节点还是右子节点
    93.         
    94.         // 情况1: 要删除的节点是叶子节点
    95.         if (!tmp->left and !tmp->right){
    96.             !lr ? pre->left = nullptr : pre->right = nullptr; // 父节点对应指针置空
    97.             return root;
    98.         }
    99.         
    100.         // 情况2: 要删除的节点只有一个子节点
    101.         if (!tmp->right)                // 只有左子节点
    102.             !lr ? pre->left = tmp->left : pre->right = tmp->left; // 用左子节点替代
    103.         else{
    104.             if (!tmp->left)             // 只有右子节点
    105.                 !lr ? pre->left = tmp->right : pre->right = tmp->right; // 用右子节点替代
    106.             else{                       // 情况3: 有两个子节点
    107.                 tmp->data = mindata(root->right)->data; // 用右子树最小节点值替换
    108.                 tmp->right = del(tmp->data, mindata(root->right)); // 删除右子树最小节点
    109.             }
    110.         }
    111.         sum--; // 节点计数减少
    112.         return root;
    113.     }
    114.    
    115.     // 前序遍历(根-左-右)
    116.     void preorder(treenode* root)
    117.     {
    118.         if (!root)              // 如果节点为空
    119.             return;             // 返回
    120.         cout << root->data << " "; // 先访问根节点
    121.         preorder(root->left);   // 再遍历左子树
    122.         preorder(root->right);  // 最后遍历右子树
    123.     }
    124.    
    125.     // 中序遍历(左-根-右)
    126.     void inorder(treenode* root){
    127.         if (!root)              // 如果节点为空
    128.             return;             // 返回
    129.         inorder(root->left);    // 先遍历左子树
    130.         cout << root->data << " "; // 再访问根节点
    131.         inorder(root->right);   // 最后遍历右子树
    132.     }
    133.    
    134. public:
    135.     // 公开插入接口
    136.     void add(int data){
    137.         add(data, root);
    138.     }
    139.    
    140.     // 查找接口
    141.     bool find(int data){
    142.         return get(data, root) != nullptr; // 转换为bool值返回
    143.     }
    144.    
    145.     // 删除接口
    146.     void del(int data){
    147.         root = del(data, root);
    148.     }
    149.    
    150.     // 中序遍历接口
    151.     void inorder(){
    152.         inorder(root);
    153.         cout << endl;
    154.     }
    155.    
    156.     // 前序遍历接口
    157.     void preorder()
    158.     {
    159.         preorder(root);
    160.         cout << endl;
    161.     }
    162. };
    复制代码
    来源:大矩学习资料
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    快速回复 返回顶部 返回列表