二叉搜索树及其Java实现

二叉搜索树(Binary Search Tree,简称BST)是一种特殊的二叉树数据结构,它满足以下特性:

  1. 有序性:对于树中的任意一个节点,其左子树中所有节点的值都小于该节点的值,而其右子树中所有节点的值都大于该节点的值。这意味着,对二叉搜索树进行中序遍历(先遍历左子树,再访问根节点,最后遍历右子树)会得到一个递增的有序序列。

  2. 结构特性:每个节点最多有两个子节点,通常称为左子节点和右子节点。没有父节点的节点称为根节点,而没有子节点的节点称为叶子节点。

二叉搜索树的这些性质使得它特别适合用于动态查找表的实现,支持几个关键操作:

  • 查找:从根节点开始,根据目标值与当前节点值的比较结果,决定是继续在左子树还是右子树中查找,直到找到目标值或遇到空节点为止。由于每次比较都可以排除一半的剩余节点,查找的平均时间复杂度为O(log n),其中n是树中节点的数量。

  • 插入:新节点总是作为叶子节点被添加。从根节点开始,沿着与新节点值的比较路径向下,直到遇到空的子节点位置,然后在此位置插入新节点。

  • 删除:删除操作相对复杂,需要考虑多种情况,如被删除节点是否有子节点,删除后需要保持二叉搜索树的性质。处理要删除的节点有两个子节点的情况时,可以找到右子树的最小值节点来替换待删除节点,然后将其删除;或者找到左子树的最大节点来替换待删除节点,然后将其删除。如下图中,加入待删除节点是10,则可以用9或者15来顶10,核心是保持BST的有序特性。

代码实现

package org.example.code;

/**
 * @author Mazai-Liu
 * @time 2024/6/22
 */
public class BST {

    public static void main(String[] args) {
        BST tree = new BST();
        tree.insert(50);
        tree.insert(30);
        tree.insert(20);
        tree.insert(40);
        tree.insert(70);
        tree.insert(60);
        tree.insert(80);

        System.out.println("Inorder traversal of the given tree:");
        tree.traversal();

        System.out.println("\n\nDelete 20");
        tree.delete(20);
        System.out.println("Inorder traversal after deletion:");
        tree.traversal();

        System.out.println("\n\nSearching for 20: " + (tree.search(20) != null ? "Found" : "Not Found"));
    }

    // 树节点定义
    static class TreeNode {
        public int val;
        public TreeNode left;
        public TreeNode right;

        public TreeNode(int val) {
            this.val = val;
        }
    }
    // BST的根节点
    private TreeNode root;

    // 搜索值
    public TreeNode search(int val) {
        return doSearch(root, val);
    }
    // 插入值
    public void insert(int key) {
        root = doAdd(root, key);
    }
    // 删除
    public void delete(int key) {
        // 用左子树的最大节点、右子树的最小节点来顶
        root = doDelete(root, key);
    }
    // 遍历
    public void traversal() {
        doTraversal(root);
    }

    // 根据有序的特性进行查找
    private TreeNode doSearch(TreeNode root, int val) {
        if(root == null || root.val == val)
            return root;

        return root.val > val ? doSearch(root.left, val) : doSearch(root.right, val);
    }

    private TreeNode doAdd(TreeNode root, int val) {
        if(root == null) 
            return new TreeNode(val);
        if(root.val > val)
            root.left = doAdd(root.left, val);
        else
            root.right = doAdd(root.right, val);
        return root;
    }
    
    // 中序遍历
    private void doTraversal(TreeNode root) {
        if(root == null)
            return;
        doTraversal(root.left);
        System.out.println(root.val);
        doTraversal(root.right);
    }

    // 删除节点并更新中间节点的引用情况
    private TreeNode doDelete(TreeNode root, int key) {
        if(root == null)
            return root;
        if(root.val > key)
            root.left =  doDelete(root.left, key);
        else if(root.val < key)
            root.right = doDelete(root.right, key);
        else {
            // 没左或没右可以直接用另一边来顶了
            if (root.right == null)
                return root.left;
            if (root.left == null)
                return root.right;

            // 找右子树的最小节点来顶
//            TreeNode theNode = root.right;
//            while (theNode.left != null) {
//                theNode = theNode.left;
//            }
//            root.val = theNode.val;
//            root.right = doDelete(root.right, theNode.val);

            // 找左子树的最大节点来顶
            TreeNode theNode = root.left;
            while (theNode.right != null) {
                theNode = theNode.right;
            }
            root.val = theNode.val;
            // 记得删除用来顶的那个元素
            root.left = doDelete(root.left, theNode.val);
        }
        return root;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值