当前位置: 首页 > news >正文

二叉排序树(BST)

二叉排序树(Binary Search Tree, BST) 是一种特殊的二叉树,它具有以下性质:

  1. 对于树中的每个节点,其左子树中的所有节点的值都小于该节点的值。

  2. 对于树中的每个节点,其右子树中的所有节点的值都大于该节点的值。

  3. 左右子树也分别是二叉排序树。

二叉排序树的主要用途是实现动态集合操作,如插入、删除和查找。


1. 二叉排序树的基本操作

1.1 查找

在二叉排序树中查找一个值:

  • 如果当前节点为空,返回 nullptr

  • 如果目标值等于当前节点的值,返回当前节点。

  • 如果目标值小于当前节点的值,递归查找左子树。

  • 如果目标值大于当前节点的值,递归查找右子树。

代码实现:
TreeNode* search(TreeNode* root, int key) {
    if (root == nullptr || root->val == key) {
        return root;
    }
    if (key < root->val) {
        return search(root->left, key);
    } else {
        return search(root->right, key);
    }
}

1.2 插入

在二叉排序树中插入一个新值:

  • 如果当前节点为空,创建一个新节点并返回。

  • 如果目标值小于当前节点的值,递归插入到左子树。

  • 如果目标值大于当前节点的值,递归插入到右子树。

代码实现:

TreeNode* insert(TreeNode* root, int key) {
    if (root == nullptr) {
        return new TreeNode(key);
    }
    if (key < root->val) {
        root->left = insert(root->left, key);
    } else if (key > root->val) {
        root->right = insert(root->right, key);
    }
    return root;
}

1.3 删除

在二叉排序树中删除一个值:

  • 如果当前节点为空,返回 nullptr

  • 如果目标值小于当前节点的值,递归删除左子树中的节点。

  • 如果目标值大于当前节点的值,递归删除右子树中的节点。

  • 如果目标值等于当前节点的值:

    • 如果节点是叶子节点,直接删除。

    • 如果节点只有一个子节点,用子节点替换当前节点。

    • 如果节点有两个子节点,用右子树的最小值(或左子树的最大值)替换当前节点的值,然后删除右子树的最小值。

代码实现:
TreeNode* deleteNode(TreeNode* root, int key) {
    if (root == nullptr) {
        return nullptr;
    }
    if (key < root->val) {
        root->left = deleteNode(root->left, key);
    } else if (key > root->val) {
        root->right = deleteNode(root->right, key);
    } else {
        // 节点是叶子节点或只有一个子节点
        if (root->left == nullptr) {
            TreeNode* temp = root->right;
            delete root;
            return temp;
        } else if (root->right == nullptr) {
            TreeNode* temp = root->left;
            delete root;
            return temp;
        }
        // 节点有两个子节点
        TreeNode* temp = findMin(root->right); // 找到右子树的最小值
        root->val = temp->val; // 用最小值替换当前节点的值
        root->right = deleteNode(root->right, temp->val); // 删除右子树的最小值
    }
    return root;
}

TreeNode* findMin(TreeNode* root) {
    while (root->left != nullptr) {
        root = root->left;
    }
    return root;
}

2. 二叉排序树的遍历

二叉排序树的中序遍历结果是一个有序序列。

2.1 中序遍历

void inorder(TreeNode* root) {
    if (root == nullptr) return;
    inorder(root->left);
    cout << root->val << " ";
    inorder(root->right);
}

2.2 前序遍历

void preorder(TreeNode* root) {
    if (root == nullptr) return;
    cout << root->val << " ";
    preorder(root->left);
    preorder(root->right);
}

2.3 后序遍历

void postorder(TreeNode* root) {
    if (root == nullptr) return;
    postorder(root->left);
    postorder(root->right);
    cout << root->val << " ";
}

3. 二叉排序树的性质

  1. 有序性:中序遍历结果是一个有序序列。

  2. 动态操作:支持高效的插入、删除和查找操作。

  3. 最坏情况:如果树退化为链表,时间复杂度会退化为 O(n)O(n)。


4. 平衡二叉排序树(BBST)

为了避免二叉排序树退化为链表,可以使用平衡二叉排序树(如 AVL 树、红黑树),它们通过旋转操作保持树的平衡,确保操作的时间复杂度为 O(log⁡n)O(logn)。


5. 代码示例:完整的二叉排序树实现

#include <iostream>
using namespace std;

struct TreeNode {
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

class BST {
private:
    TreeNode* root;

    TreeNode* insert(TreeNode* root, int key) {
        if (root == nullptr) {
            return new TreeNode(key);
        }
        if (key < root->val) {
            root->left = insert(root->left, key);
        } else if (key > root->val) {
            root->right = insert(root->right, key);
        }
        return root;
    }

    TreeNode* deleteNode(TreeNode* root, int key) {
        if (root == nullptr) {
            return nullptr;
        }
        if (key < root->val) {
            root->left = deleteNode(root->left, key);
        } else if (key > root->val) {
            root->right = deleteNode(root->right, key);
        } else {
            if (root->left == nullptr) {
                TreeNode* temp = root->right;
                delete root;
                return temp;
            } else if (root->right == nullptr) {
                TreeNode* temp = root->left;
                delete root;
                return temp;
            }
            TreeNode* temp = findMin(root->right);
            root->val = temp->val;
            root->right = deleteNode(root->right, temp->val);
        }
        return root;
    }

    TreeNode* findMin(TreeNode* root) {
        while (root->left != nullptr) {
            root = root->left;
        }
        return root;
    }

    void inorder(TreeNode* root) {
        if (root == nullptr) return;
        inorder(root->left);
        cout << root->val << " ";
        inorder(root->right);
    }

public:
    BST() : root(nullptr) {}

    void insert(int key) {
        root = insert(root, key);
    }

    void deleteNode(int key) {
        root = deleteNode(root, key);
    }

    void inorder() {
        inorder(root);
        cout << endl;
    }
};

int main() {
    BST tree;
    tree.insert(50);
    tree.insert(30);
    tree.insert(20);
    tree.insert(40);
    tree.insert(70);
    tree.insert(60);
    tree.insert(80);

    cout << "Inorder traversal: ";
    tree.inorder();

    cout << "Delete 20\n";
    tree.deleteNode(20);
    tree.inorder();

    cout << "Delete 30\n";
    tree.deleteNode(30);
    tree.inorder();

    cout << "Delete 50\n";
    tree.deleteNode(50);
    tree.inorder();

    return 0;
}

6. 总结

  • 二叉排序树是一种高效的数据结构,支持动态集合操作。

  • 通过中序遍历可以得到有序序列。

  • 为了避免退化为链表,可以使用平衡二叉排序树。

掌握二叉排序树的基本操作和性质,是学习更高级数据结构(如 AVL 树、红黑树)的基础!

相关文章:

  • 平板作为电脑拓展屏
  • 组合模式 Composite Pattern
  • 【蓝桥杯集训·每日一题2025】 AcWing 6123. 哞叫时间 python
  • CSRF 漏洞原理演示 基本绕过(同源 异源) 配合XSSToken值校验复用删除
  • 2025年02月18日Github流行趋势
  • 【机器学习】超参数调优指南:交叉验证,网格搜索,混淆矩阵——基于鸢尾花与数字识别案例的深度解析
  • 【Mysql】索引
  • 深入解析「卡顿帧堆栈」 | UWA GPM 2.0 技术细节与常见问题
  • 独立开发者倾向于使用哪些技术栈
  • 知识篇 | DeepSeek企业部署模式主要有6种
  • 【AI面板识别】
  • 3.10 实战Hugging Face Transformers:从文本分类到模型部署全流程
  • 基于TI的TDA4高速信号仿真条件的理解 4.1 4.2
  • AI 安全时代:SDL与大模型结合的“王炸组合”——技术落地与实战指南
  • CTF-内核pwn入门1: linux内核模块基础原理
  • 25工商管理研究生复试面试问题汇总 工商管理专业知识问题很全! 工商管理复试全流程攻略 工商管理考研复试真题汇总
  • 在Windows系统中安装Open WebUI并连接Ollama
  • OpenCalib(四)水平棋盘格标靶检测
  • 【AI论文】InfiniteHiP:在单块GPU上将语言模型上下文扩展至300万个令牌
  • Windows 启动 SSH 服务
  • 2025柯桥时尚周启幕:国际纺都越来越时尚
  • 康子兴评《文明的追求》|野人脚印:鲁滨逊的恐惧与文明焦虑
  • 中国以“大幅开放市场”回应贸易保护主义
  • 巴国家安全委员会授权军方自主决定对印反击措施
  • 五一期间7名游客接连被困青海荒漠,警方提醒严禁非法穿越
  • 降准又降息!央行发布3类10项措施