JAVA实现 二叉排序树查找,插入,删除

一、二叉树结点定义类TreeNode:

 

class TreeNode{
    public int data;
    public TreeNode left;
    public TreeNode right;
    TreeNode(int data){
        this.data=data;
    }
}

二、插入新的节点这里介绍两种方法,递归与非递归方式:

 

1.递归方式

 

    //添加节点(递归模式)
    public static boolean AddTreeNode1(TreeNode root, int data){
        TreeNode treeNode=new TreeNode(data);
        //树为空
        if(root==null){
            root=treeNode;
            return true;
        }
        //比根节点小,插入到左子树
        if(root.data>data){
            if(root.left==null){
                root.left=treeNode;
                return true;
            }else
                return AddTreeNode1(root.left, data);
        }else if(root.data<data){       //比根节点大,插入到右子树
            if(root.right==null){
                root.right=treeNode;
                return true;
            }else
                return AddTreeNode1(root.right,data);
        }else
            return false;
    }

 

2.非递归方式(迭代)

 

    //增加节点非递归模式
    public static boolean AddTreeNode2(TreeNode root, int data){
        //树为空
        if(root==null){
            root=new TreeNode(data);
            return true;
        }
        TreeNode treeNode=new TreeNode(data);
        TreeNode currNode=root;
        while(true){
            if(currNode.data>data){
                if(currNode.left!=null)
                    currNode=currNode.left;
                else{
                    currNode.left=treeNode;
                    return true;
                }
            }else if(currNode.data<treeNode.data){
                if(currNode.right!=null)
                    currNode=currNode.right;
                else {
                    currNode.right=treeNode;
                    return true;
                }
            }else
                return false;
        }
    }

 

 

 

 

 

 

 

三、查找:

 

    public static boolean SearchTreeNode(TreeNode root, int data){
        if(root==null){
            return false;
        }else if(root.data==data){
            return true;
        }else if(root.data>data){
            return SearchTreeNode(root.left,data);
        }else{
            return SearchTreeNode(root.right,data);
        }
    }

 

 

 

四、删除

删除可为BST问题最为复杂的一部分,需要考虑一下要删除的节点的四种情况:

(1)该节点为叶子节点,删除即可

(2)该节点只有左子树,没有右子树,删除后将该节点的左子树连接到该节点的父节点(主要判断该节点为左节点还是右节点)

(3)该节点只有右子树,没有左子树,删除后将该节点的右子树连接到该节点的父节点(主要判断该节点为左节点还是右节点)

(4)该节点既有左子树,也有右子树,这时候删除比较复杂,可以分为两种情况:

首先,我们知道二叉排序树经过中序遍历后得到的是一个递增有序序列,该节点的前一个即为直接前驱,后一个为直接后继。我们要得到直接前驱和直接后继的节点。

方法一:a.得到该删除节点的左节点,如果此左节点没有右节点,则该左节点即为直接前驱;

              b.左节点有右节点,则一直沿最右侧右节点迭代下去,最后面的那个即为直接前驱。

 

方法二:a.得到该删除节点的右节点,如果此右节点没有左节点,则该右节点即为直接后继;

              b.右节点有左节点,则一直沿最左侧左节点迭代下去,最后面的那个即为直接后继。

以上四种情况均要考虑要删除的节点为根节点root的情况。

源代码如下:

    //删除
    public static boolean DeleteNode(TreeNode root, int data){
        //current为查找得到的节点
        TreeNode current=root;
        //parent为时刻更新父节点
        TreeNode parent=root;
        //tempParent为同时存在左右子树的迭代临时父节点
        TreeNode tempParent=root;
        //isLeft记录current节点的左右属性
        boolean isLeft=true;
        while(current.data!=data){
            parent=current;
            //到左子树查找
            if(current.data>data){
                isLeft=true;
                current=current.left;
            }else if(current.data<data){ //到右子树查找
                isLeft=false;
                current=current.right;
            }
            //查不到,返回false
            if(current==null)
                return false;
        }
        //第一种情况:删除节点为叶节点
        if(current.left==null && current.right==null){
            if(current==root)
                root=null;
            if(isLeft) {
                parent.left = null;
            }else{
                parent.right = null;
            }
            return true;
        }else if(current.right==null){    //第二种情况:删除节点只有左节点
            if(current==root)
                root=current.left;
            else if(isLeft)
                parent.left=current.left;
            else
                parent.right=current.left;
            return true;
        }else if(current.left==null){    //第三种情况:删除节点只有右节点
            if(current==root)
                root=current.right;
            else if(isLeft)
                parent.left=current.right;
            else
                parent.right=current.right;
            return true;
        }else{  //第四种情况:删除节点均存在左节点和右节点
            if(current==root){
                root=root.left;
            }
            TreeNode tempNode=current.left;
            //没有左节点
            if(tempNode.right==null){
                if(isLeft)
                    parent.left=tempNode;
                else
                    parent.right=tempNode;
            }else{  //存在左节点,迭代到最右侧子节点,即直接前驱
                while(tempNode.right!=null){
                    tempParent=tempNode;
                    tempNode=tempNode.right;
                }
                if(isLeft){    //为左节点,连接
                    parent.left=tempNode;
                    parent.left.left=current.left;
                }else{  //为右节点,连接
                    parent.right=tempNode;
                    parent.right.left=current.left;
                }
                //删除前驱节点,连接
                if(tempNode.left==null)
                    tempParent.right=null;
                else
                    tempParent.right=tempNode.left;
            }
            return true;
        }
    }

 

五、二叉树中序遍历

 

    //二叉树中序遍历
    public static void midSort(TreeNode root){
        if(root==null){
            return;
        }
        midSort(root.left);
        System.out.print(root.data+" ");
        midSort(root.right);
    }


六、由二叉排序树得到最小值(最大值同理,未加)

 

 

    //由二叉排序树得到最小值
    public static int getMin(TreeNode root){
        if(root.left==null) {
            return root.data;
        }else{
            return getMin(root.left);
        }
    }

 

 

 

综上,测试主函数代码如下:

 

public static void main(String[] args){
        int[] a=new int[]{62,88,58,47,35,73,51,99,37,93};
        TreeNode root=new TreeNode(a[0]);
        for(int i=1; i<a.length; i++){
            AddTreeNode1(root, a[i]);
        }
        System.out.println("中序遍历结果为:");
        midSort(root);
        System.out.println("47存在:"+SearchTreeNode(root,47));
        AddTreeNode1(root,100);
        System.out.println("添加100后,中序遍历结果为:");
        midSort(root);
        System.out.println("添加100后,100存在:"+SearchTreeNode(root,100));


输出结果为:

 

 

中序遍历结果为:
35 37 47 51 58 62 73 88 93 99 47存在:true
添加100后,中序遍历结果为:
35 37 47 51 58 62 73 88 93 99 100 添加100后,100存在:true
删除100后,中序遍历结果为:
35 37 47 51 58 62 73 88 93 99 删除100后,100存在:false

 

 

参考博文链接

 

 

 

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值