二叉搜索树

有序数组 vs 二叉搜索树(BST)


有序数组的优缺点

  • 优点

    • 查找快(O(log n)):可以用二分查找快速定位数据。

  • 缺点

    • 插入/删除慢(O(n)):每次插入或删除都需要移动后面的所有元素。

    • 示例

      • 插入 17 → 后面所有元素后移。

      • 删除 17 → 后面所有元素前移。

适用场景:适合静态数据(很少修改,频繁查找)。


二叉搜索树(BST)简介

  • 定义:一种能高效支持查找、插入、删除(均摊 O(log n))的树形结构。

  • 核心规则

    • 左子树的所有节点 < 根节点。

    • 右子树的所有节点 > 根节点。

    • 中序遍历结果是从小到大有序的

  • 比如下面这棵树就是一颗二叉搜索树


BST 的基本操作

 (1) 插入(Insert)

  • 若插入值小于当前节点值,递归插入到左子树。
  • 若插入值大于当前节点值,递归插入到右子树。
  • public TreeNode insert(TreeNode root, int val) {
        if (root == null) {
            return new TreeNode(val);
        }
        if (val < root.val) {
            root.left = insert(root.left, val);
        } else if (val > root.val) {
            root.right = insert(root.right, val);
        }
        return root;
    }
    

(2) 查找(Search)

  • 实际上就是二分查找的思想

  • 即从根节点开始比较。

  • 目标值 < 当前节点 → 往左子树找。

  • 目标值 > 当前节点 → 往右子树找。

  • 找到相等值 → 成功;遇到空节点 → 失败。

  • public TreeNode search(TreeNode root, int val) {
        if (root == null || root.val == val) {
            return root;
        }
        if (val < root.val) {
            return search(root.left, val);
        } else {
            return search(root.right, val);
        }
    }
    

(3) 删除(Delete)

public TreeNode delete(TreeNode root, int val) {
    if (root == null) return null;
    
    if (val < root.val) {
        root.left = delete(root.left, val);
    } else if (val > root.val) {
        root.right = delete(root.right, val);
    } else {
        // Case 1 & 2: 无子节点或只有一个子节点
        return root.left == null?root.right:root.left;
        
        // Case 3: 有两个子节点
        TreeNode minNode = findMin(root.right);
        root.val = minNode.val;
        root.right = delete(root.right, minNode.val);
    }
    return root;
}

private TreeNode findMin(TreeNode node) {
    while (node.left != null) {
        node = node.left;
    }
    return node;
}

分三种情况处理:

  • 叶子节点:直接删除。

  • 只有左或右子树(如 10 只有左子树):用它的唯一子树替代自己。

  • 有左右子树(如根节点 9):

    • 找到该节点的 前驱(左子树最大节点) 或 后继(右子树最小节点)

    • 用前驱或后继的值覆盖待删除节点。

    • 删除原来的前驱/后继节点(它一定是叶子节点或单子节点,递归处理)。

    • 这里演示一下用左子树中的最大节点覆盖待删除节点

    • 为什么选这两个节点?

      • 前驱:是待删除节点在中序遍历序列中的前一个节点,替换后不会破坏BST性质。

      • 后继:是待删除节点在中序遍历序列中的后一个节点,同样保证结构正确。


BST 的极端情况与问题

  • 问题:如果插入的数据本身有序(如 1, 2, 3, 4, 5),BST 会退化成链表,查找效率降为 O(n)

    • 示例:依次插入 1, 2, 3, 4, 5 → 树变成一条向右的链。

  • 解决方案:使用平衡二叉搜索树(如 AVL 树、红黑树),通过旋转操作保持树平衡。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值