java实现二叉查找树

1.二叉树概念

概念:二叉树是一棵树,其中每个节点不能多于两个儿子

2.图解分析

2.1 模拟器地址

二叉树:https://www.cs.usfca.edu/~galles/visualization/BST.html
所有数据结构:https://www.cs.usfca.edu/~galles/visualization/Algorithms.html

2.2添加

如果依次添加6,2,1,4,3,5,8节点,结果如下图
第一个添加的节点为根,后面添加的节点大于根往右,小于根往左
在这里插入图片描述

2.3 删除

2.3.1 删除节点1

在这里插入图片描述

  • 第一步:1小于6 向左寻找到2
  • 第二步:1小于2 向左寻找1
  • 第三步:设置2的左边节点为节点1的左边节点(如果有左边节点的话) 图中为null
  • 第三步核心代码: root = (root.left != null) ? root.left : root.right;

2.3.2 删除节点2

在这里插入图片描述

  • 第一步:2小于6 向左寻找到3
  • 第二步:2小于3 向左寻找到2
  • 第三步:设置3的左边节点为2的左边节点
  • 第三步核心代码:root = (root.left != null) ? root.left : root.right;
  • ps:第一种情况何和第二种情况本质上是一样的,只是第一种情况恰好被删除节点没有儿子

2.3.3 删除节点4

当需要删除的节点有左右两个儿子的时候

2.3.3.1第一种实现方式

在这里插入图片描述

  • 第一步:4小于6 向左寻找到2
  • 第二步:4大于2 向右寻找4为删除节点
  • 第三步:找到4节点右树中最小的节点5作为替换节点
  • 第四步:设置2的右节点为5(只替换节点本身,原左边3自动转化为节点5的左边节点)
  • 第五步:删除原来5节点中的5节点 剩余节点为5的右节点
  • 核心代码:
    //找到右树中的最小节点5代替4
    root.element = findMin(root.right).element; //找到5
    //删除原来5节点中的5节点 剩余节点为5的右节点
    root.right = remove(root.element, root.right);
    //root.left 还是原来的3
2.3.3.2第二种实现方式

在这里插入图片描述

  • 第一步:4小于6 向左寻找到2
  • 第二步:4大于2 向右寻找4为删除节点
  • 第三步:找到4节点左树中最大的节点3作为替换节点
  • 第四步:设置2的右节点为3(只替换节点本身,原右边5自动转化为节点3的右边节点)
  • 第五步:删除原来3节点中的3节点 剩余节点为3的左节点
  • 核心代码:
    //找到左树中的最大节点3代替4
    root.element = findMax(root.left).element; //找到3
    //删除原来3节点中的3节点 剩余节点为3的左节点
    root.left= remove(root.element, root.left);
    //root.right 还是原来的5

3.代码

3.1树节点

/**
 * 二叉树节点
 */
public class BinaryNode<T> {
    T element;
    BinaryNode<T> left;
    BinaryNode<T> right;

    public BinaryNode(T element) {
        this(element, null, null);
    }

    public BinaryNode(T element, BinaryNode<T> left, BinaryNode<T> right) {
        this.element = element;
        this.left = left;
        this.right = right;
    }
    
}

3.2插入

public void insert(T x) {
        root = insert(x, root);
    }
/**
     * 添加节点
     *
     * @param x    插入节点
     * @param root 根节点
     */
    private BinaryNode<T> insert(T x, BinaryNode<T> root) {

        //如果根节点为空,则当前x节点为根节点
        if (null == root) {
            return new BinaryNode(x);
        }
      
        int compareResult = x.compareTo(root.element);

        //小于当前根节点 将x插入根节点的左边
        if (compareResult < 0) {
            root.left = insert(x, root.left);
        } else if (compareResult > 0) {
            //大于当前根节点 将x插入根节点的右边
            root.right = insert(x, root.right);
        } else {

        }
        return root;
    }

3.3删除

/**
     * 删除节点
     *
     * @param x    节点
     * @param root 根节点
     */
    private BinaryNode<T> remove(T x, BinaryNode<T> root) {

        if (null == root) {
            return root;
        }

        int compareResult = x.compareTo(root.element);

        //小于当前根节点
        if (compareResult < 0) {
            root.left = remove(x, root.left);
        } else if (compareResult > 0) {
            //大于当前根节点
            root.right = remove(x, root.right);
        } else if (root.left != null && root.right != null) {
            //找到右边最小的节点
            root.element = findMin(root.right).element;
            //当前节点的右边等于原节点右边删除已经被选为的替代节点
            root.right = remove(root.element, root.right);
        } else {
            root = (root.left != null) ? root.left : root.right;
        }
        return root;
    }

3.4 完整代码

public class BinarySearchTree<T extends Comparable<? super T>> {

    private BinaryNode<T> root;

    public void insert(T x) {
        root = insert(x, root);
    }

    public void remove(T x) {
        root = remove(x, root);
    }

    public T findMin() {
        return findMin(root).element;
    }


    public void makeEmpty() {
        root = null;
    }

    public boolean isEmpty() {
        return root == null;
    }

    /**
     * 添加节点
     *
     * @param x    插入节点
     * @param root 根节点
     */
    private BinaryNode<T> insert(T x, BinaryNode<T> root) {

        //如果根节点为空,则当前x节点为根及诶单
        if (null == root) {
            return new BinaryNode(x);
        }

        int compareResult = x.compareTo(root.element);

        //小于当前根节点 将x插入根节点的左边
        if (compareResult < 0) {
            root.left = insert(x, root.left);
        } else if (compareResult > 0) {
            //大于当前根节点 将x插入根节点的右边
            root.right = insert(x, root.right);
        } else {

        }
        return root;
    }

    /**
     * 删除节点
     *
     * @param x    节点
     * @param root 根节点
     */
    private BinaryNode<T> remove(T x, BinaryNode<T> root) {

        if (null == root) {
            return root;
        }

        int compareResult = x.compareTo(root.element);

        //小于当前根节点
        if (compareResult < 0) {
            root.left = remove(x, root.left);
        } else if (compareResult > 0) {
            //大于当前根节点
            root.right = remove(x, root.right);
        } else if (root.left != null && root.right != null) {
            //找到右边最小的节点
            root.element = findMin(root.right).element;
            //当前节点的右边等于原节点右边删除已经被选为的替代节点
            root.right = remove(root.element, root.right);
        } else {
            root = (root.left != null) ? root.left : root.right;
        }
        return root;
    }

    /**
     * 找最小节点
     *
     * @param root 根节点
     */
    private BinaryNode<T> findMin(BinaryNode<T> root) {
        if (root == null) {
            return null;
        } else if (root.left == null) {
            return root;
        }
        return findMin(root.left);
    }

    /**
     * 找最大节点
     *
     * @param root 根节点
     */
    private BinaryNode<T> findMax(BinaryNode<T> root) {
        if (root == null) {
            return null;
        } else if (root.right == null) {
            return root;
        } else {
            return findMax(root.right);
        }
    }

    public void printTree() {
        if (isEmpty()) {
            System.out.println("节点为空");
        } else {
            printTree(root);
        }
    }


    public void printTree(BinaryNode<T> root) {
        if (root != null) {
            System.out.print(root.element);
            if (null != root.left) {
                System.out.print("左边节点" + root.left.element);
            }
            if (null != root.right) {
                System.out.print("右边节点" + root.right.element);
            }
            System.out.println();
            printTree(root.left);
            printTree(root.right);
        }
    }

}

4.测试

代码:

 @Test
    public void test2(){
        BinarySearchTree testTree = new BinarySearchTree();
        testTree.insert(6);
        testTree.insert(2);
        testTree.insert(8);
        testTree.insert(1);
        testTree.insert(4);
        testTree.insert(3);
        testTree.insert(5);

        testTree.printTree();

        testTree.remove(2);

        System.out.println("======删除2节点之后======");

        testTree.printTree();
    }

测试截图:
在这里插入图片描述

5.参考书籍

《数据结构与算法分析》第三版

6.系列链接

下一篇:java实现AVL树

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值