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

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

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

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

1.递归方式

<span style="font-size:18px;">    <span style="color:#ff0000;">//添加节点(递归模式)</span>
    public static boolean AddTreeNode1(TreeNode root, int data){
        TreeNode treeNode=new TreeNode(data);
        <span style="color:#ff0000;">//树为空</span>
        if(root==null){
            root=treeNode;
            return true;
        }
        <span style="color:#ff0000;">//比根节点小,插入到左子树</span>
        if(root.data>data){
            if(root.left==null){
                root.left=treeNode;
                return true;
            }else
                return AddTreeNode1(root.left, data);
        }else if(root.data<data){             <span style="color:#ff0000;">//比根节点大,插入到右子树</span>
            if(root.right==null){
                root.right=treeNode;
                return true;
            }else
                return AddTreeNode1(root.right,data);
        }else
            return false;
    }</span><span style="background-color: rgb(255, 255, 255);"><span style="font-size:18px;"> 点击打开链接</span></span>

2.非递归方式(迭代)

<span style="font-size:18px;">   <span style="color:#ff0000;"> //增加节点非递归模式</span>
    public static boolean AddTreeNode2(TreeNode root, int data){
        <span style="color:#ff0000;">//树为空</span>
        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;
        }
    }</span>

三、查找:

    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的情况。

源代码如下:

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

参考博文链接


    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/qq_35181209/article/details/52798166
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞