二叉排序树

二叉排序树

数据结构预算法章节目录>>

基本介绍

二叉排序树:BST:(Binary Sort(Search) Tree),对于二叉排序树的任何一个非叶子节点,要求左子树的值比当前节点的值小,右子节点的值比当前节点的值大。

特别说明:如果有相同的值,可以将该节点放在左子节点或右子节点。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o2FK19r4-1578842411615)(images/20.png)]

二叉排序树的创建和遍历

代码

//添加节点的方法
    //递归的形式添加节点,注意需要满足二叉排序树的要求
    public void add (Node node){

        if(node==null){
            return;
        }

        //判断传入节点的值和我们当前子树的跟节点值的关系
        //待添加节点小于当前节点
        if(node.value<this.value){
            //当前节点左子节点为空
            if(this.left==null){
                this.left = node;
            }else{
                this.left.add(node);//递归的向左子树添加
            }
        }else{//添加节点的值大于当前节点的值
            //右子节点为空
            if(this.right==null){
                this.right=node;
            }else{
                //递归的向右子树添加
                this.right.add(node);
            }

        }
    }

二叉排序树的删除

  1. 删除叶子节点 比如 (2,5,9,12)
  2. 删除只有一颗子树的节点 (1)
  3. 删除有两颗子树的节点 (7,3,10)


删除叶子节点

  1. 需要先去找到要删除的节点是存在的,targetNode

  2. 确定目标节点targetNode的父节点 parentNode(还需要考虑是否有父节点)

  3. 判断targetNode是parent的左子节点还是右子节点

  4. 根据前面的情况来对应的删除

    ​ 4.1、如果是左子节点:parent.left = null

    ​ 4.2、如果是右子节点:parent.right = null



删除只有一颗子树的节点

  1. 需要先去找到要删除的节点是存在的,targetNode

  2. 确定目标节点targetNode的父节点 parentNode(还需要考虑是否有父节点)

  3. 确定targetNode的子节点是左子节点还是右子节点

  4. targetNode是parentNode的左子节点还是右子节点

  5. 根据前面的情况来对应的删除

    ​ ~~5.1、targetNode是parent的左子节点,targetNode的子节点是子节点; ==parent.left = targetNode.left==~

    5.2、targetNode是parent的左子节点,targetNode的子节点是右节点 : parent.left = targetNode.right~

       ~~5.3、targetNode是parent的右子节点,targetNode的子节点是右子节点; ==parent.right = targetNode.right==~~
    

    5.4

    如果targetNode有左子节点

    ​ 5.1、如果targetNode是parentNode的左子节点:parentNode.left = taregetNode.left

    ​ 5.2、如果targetNode是parentNode的右子节点:parentNode.right = taregetNode.left

如果targetNode有右子节点

​ 5.3、如果targetNode是parentNode的左子节点:parentNode.left=taregetNode.right

​ 5.4、如果targetNode是parentNode的右子节点:parentNode.right=taregetNode.right

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1g1ASW9J-1578842411617)(images/21.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-53lkrgFS-1578842411618)(images/22.png)]

删除有两颗子树的节点

  1. 需要先去找到要删除的节点是存在的,targetNode

  2. 确定目标节点targetNode的父节点 parentNode(还需要考虑是否有父节点)

  3. 从targetNode的右子树最小的节点

  4. 用临时变量,将最小节点的值保存temp

  5. 删除该最小节点

  6. targetNode.value = temp

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tSK0Ex0I-1578842411618)(images/23.png)]

 /**
     * @param node  待传入的节点(当做一颗排序树的根节点)
     * @return  以node为跟节点的二叉排序树最小节点的值
     * //1、返回以node为跟节点的二叉排序树最小节点的值
     * //2、删除 以node为跟节点的二叉排序树最小节点的值
     * */
    public int deleteRightMin(Node node){
        Node temp= node;
        //循环的查找左节点,直到找到最小值
        while(temp.left!=null){
            temp = temp.left;
        }
        //这时target就指向了最小的值
        //删除最小节点
        deleteNode(temp.value);
        return temp.value;
    }


    //删除节点
    public  void deleteNode(int value){
        if(this.root==null){
            return;
        }else{
            //1、先根据需求查找要删除的节点  targetNode
            Node targetNode = Search(value);
            //如果没有找到要删除的节点
            if(targetNode==null){
                return;
            }


            //如果发现当前二叉排序树只有一个节点
            if(root.left==null && root.right==null){
                root = null;
            }

            //去查找targetNode的父节点
            Node parent = searchParent(value);
            //如果要删除的节点是叶子节点
            if(targetNode.left==null&&targetNode.right==null){
                //判断targetNode是parentNode的左子节点还是右子节点
                if(parent.left!=null&&parent.left==targetNode){
                    parent.left=null;
                }

                if(parent.right!=null&&parent.right==targetNode){
                    parent.right=null;
                }

                //要删除的节点有两个子节点
            }else if(targetNode.left!=null&&targetNode.right!=null){

                //从右子树找最小的 取待待删除的节点
                int minValue = deleteRightMin(targetNode.right);
                targetNode.value = minValue;


            }else{//要删除的节点有一个子节点

                //要删除的节点有一个右子节点
                if(targetNode.right!=null){
                    //要删除的节点是parent的左子节点
                    if( parent.left==targetNode){
                        parent.left = targetNode.right;
                    //要删除的节点是parent的右子节点
                    }else if( parent.right==targetNode){
                        parent.right=targetNode.right;
                    }

                }else{//要删除的节点有一个左子节点
                    //要删除的节点是parent的左子节点
                    if(parent.left==targetNode){
                        parent.left = targetNode.left;

                   //要删除的节点是parent的右子节点
                    }else if(parent.right==targetNode){
                        parent.right=targetNode.left;
                    }
                }

            }
        }

    }


}

代码

package J树的提高.binarysortTree;


/**
 * @Author Zhou  jian
 * @Date 2020 ${month}  2020/1/12 0012  20:46
 */
public class BinarySortTreeDemo {

    public static void main(String[] args) {


            int[] arr = {7,3,10,12,5,1,9,2};
            BinarySortTree binarySortTree = new BinarySortTree();

            //循环的添加节点到二叉排序树
            for(int i =0;i<arr.length;i++){
                binarySortTree.add(new Node(arr[i]));
            }

            //中序遍历 二叉排序树
            System.out.println("中序遍历二叉排序与树");
            binarySortTree.infixOrder(); //1 3 5 7 9 10 12


            //测试删除叶子节点
//        binarySortTree.deleteNode(9);
//        System.out.println("删除节点后中序遍历二叉排序与树");
//        binarySortTree.infixOrder(); //1 3 5 7 9 10 12

//             //测试删除只有一个子节点的节点
//        binarySortTree.deleteNode(1);
//        System.out.println("删除只有一个节点的节点");
//        binarySortTree.infixOrder(); //1 3 5 7 9 10 12

        //删除有两个子树的节点
        System.out.println("删除you2个节点的节点");
        binarySortTree.deleteNode(7);
        binarySortTree.infixOrder(); //1 3 5 7 9 10 12



    }


}
//创建二叉排序树
class BinarySortTree{
    //头结点
    private Node root;

    //添加节点的方法
    public  void  add(Node node){
        //如果root为空,则直接赋值root怪
        if(root==null){
            root = node;
        }else{
            root.add(node);
        }
    }


    //中序遍历
    public  void infixOrder(){
        if(root!=null){
            root.infixOrder();
        }else{
            System.out.println("当前二叉排序树为空不能遍历");
        }
    }

    //查找节点
    public Node Search(int value){
        if(root==null){
            return null;
        }else{
            return root.Search(value);
        }
    }


    //查找父节点
    public Node searchParent(int value){
        if(root==null){
            return null;
        }else{
            return root.searchParent(value);
        }
    }



    /**
     * @param node  待传入的节点(当做一颗排序树的根节点)
     * @return  以node为跟节点的二叉排序树最小节点的值
     * //1、返回以node为跟节点的二叉排序树最小节点的值
     * //2、删除 以node为跟节点的二叉排序树最小节点的值
     * */
    public int deleteRightMin(Node node){
        Node temp= node;
        //循环的查找左节点,直到找到最小值
        while(temp.left!=null){
            temp = temp.left;
        }
        //这时target就指向了最小的值
        //删除最小节点
        deleteNode(temp.value);
        return temp.value;
    }


    //删除节点
    public  void deleteNode(int value){
        if(this.root==null){
            return;
        }else{
            //1、先根据需求查找要删除的节点  targetNode
            Node targetNode = Search(value);
            //如果没有找到要删除的节点
            if(targetNode==null){
                return;
            }


            //如果发现当前二叉排序树只有一个节点
            if(root.left==null && root.right==null){
                root = null;
            }

            //去查找targetNode的父节点
            Node parent = searchParent(value);
            //如果要删除的节点是叶子节点
            if(targetNode.left==null&&targetNode.right==null){
                //判断targetNode是parentNode的左子节点还是右子节点
                if(parent.left!=null&&parent.left==targetNode){
                    parent.left=null;
                }

                if(parent.right!=null&&parent.right==targetNode){
                    parent.right=null;
                }

                //要删除的节点有两个子节点
            }else if(targetNode.left!=null&&targetNode.right!=null){

                //从右子树找最小的 取待待删除的节点
                int minValue = deleteRightMin(targetNode.right);
                targetNode.value = minValue;


            }else{//要删除的节点有一个子节点

                //要删除的节点有一个右子节点
                if(targetNode.right!=null){
                    //要删除的节点是parent的左子节点
                    if( parent.left==targetNode){
                        parent.left = targetNode.right;
                    //要删除的节点是parent的右子节点
                    }else if( parent.right==targetNode){
                        parent.right=targetNode.right;
                    }

                }else{//要删除的节点有一个左子节点
                    //要删除的节点是parent的左子节点
                    if(parent.left==targetNode){
                        parent.left = targetNode.left;

                   //要删除的节点是parent的右子节点
                    }else if(parent.right==targetNode){
                        parent.right=targetNode.left;
                    }
                }

            }
        }

    }


}


//创建Node节点
class Node{

    int value;
    Node left;
    Node right;

    public Node(int value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "Node{" +
                "value=" + value +
                '}';
    }

    //添加节点的方法
    //递归的形式添加节点,注意需要满足二叉排序树的要求
    public void add (Node node){

        if(node==null){
            return;
        }

        //判断传入节点的值和我们当前子树的跟节点值的关系
        //待添加节点小于当前节点
        if(node.value<this.value){
            //当前节点左子节点为空
            if(this.left==null){
                this.left = node;
            }else{
                this.left.add(node);//递归的向左子树添加
            }
        }else{//添加节点的值大于当前节点的值
            //右子节点为空
            if(this.right==null){
                this.right=node;
            }else{
                //递归的向右子树添加
                this.right.add(node);
            }
        }
    }


    //中序遍历
    public  void infixOrder(){

        if(this.left!=null){
            this.left.infixOrder();
        }

        System.out.println(this);

        if(this.right!=null){
            this.right.infixOrder();
        }
    }



    //查找要删除的节点
    /**
     * @param value 希望删除节点的值
     */
    public Node Search(int value){
       if(value==this.value){//找到就是该节点
           return this;
       }else if(value<this.value){ //如果查找的值小于当前节点。向左子树递归查找
           //如果左子节点为空,就不再找
           if(this.left==null){
               return null;
           }
           return  this.left.Search(value);
       }else{
           if(this.right==null){
               return null;
           }
           return this.right.Search(value);
       }
    }

    //查找要删除节点的父亲节点
    /**
     *
     * @param value
     * @return  返回的是要删除节点的父节点
     */
    public Node searchParent(int value){
        //如果当前节点就是要删除节点的父节点就返回
        if(((this.left!=null) &(this.left.value==value))||((this.right!=null) &(this.right.value==value))){
            return this;
        }else {
            //如果查找的值小于当前节点的值并且当前节点的左子节点不为空
            //递归向左子节点删除
            if((this.left!=null)&&(value<this.value)){
                return this.left.searchParent(value);
            } else if((this.right!=null)&&(value>this.value)){//向右子树递归查找
                return this.right.searchParent(value);
            }else{
                return null;//没有找到父节点
            }

        }
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值