基本数据结构之二叉排序树(用Java语言实现)

二叉排序树

二叉排序树(Binary Sort Tree),又称二叉查找树(Binary Search Tree)或二叉搜索树。二叉排序树为满足以下条件的树:
◎ 若左子树不空,则左子树上所有节点的值均小于它的根节点的值;
◎ 若右子树不空,则右子树上所有节点的值均大于或等于它的根节点的值;
◎ 左、右子树也分别为二叉排序树。如图4-10所示便是一个二叉排序树。

在这里插入图片描述

插入操作

在二叉排序树中进行插入操作时只需找到待插入的父节点,将数据插入即可,具体流程如下。
(1)将待插入的新节点与当前节点进行比较,如果两个节点的值相同,则表示新节点已经存在于二叉排序树中,直接返回false。
(2)将待插入的新节点与当前节点进行比较,如果待插入的新节点的值小于当前节点的值,则在当前节点的左子树中寻找,直到左子树为空,则当前节点为要找的父节点,将新节点插入当前节点的左子树即可。

(3)将待插入的新节点与当前节点进行比较,如果待插入的新节点的值大于当前节点的值,则在当前节点的右子树中寻找,直到右子树为空,则当前节点为要找的父节点,将新节点插入当前节点的右子树即可。具体的插入流程如图4-11所示。

在这里插入图片描述

删除操作

二叉排序树的删除操作?要分为三种情况:待删除的节点没有子节点;待删除的节点只有一个子节点;待删除的节点有两个子节点。
具体情况如下。
(1)在待删除的节点没有子节点时,直接删除该节点,即在其父节点中将其对应的子节点置空即可。如图 4-12所示,要删除的节点14没有子节点,则直接将其删除即可。

在这里插入图片描述

(2)在待删除的节点只有一个子节点时,使用子节点替换当前节点,然后删除该节点即可。如图 4-13所示,要删除的节点 5有一个子节点 8,则使用子节点 8替换需要删除的节点5,然后删除节点5的数据即可。

在这里插入图片描述

(3)在待删除的节点有两个子节点时,首先查找该节点的替换节点(替换节点为左子树中的最大节点或者右子树中的最小节点),然后替换待删除的节点为替换节点,最后删除替换节点。如图 4-14所示,要删除的节点 4有两个子节点,其左子树最小的节点为2,其右子树最小的节点为5,因此有两种结果。
在这里插入图片描述

查找操作
二叉排序树的查找方式和效率接近二分查找法,因此可以很容易获取最大(最右最深子节点)值和最小(最左最深子节点)值,具体的查找流程为:将要查找的数据与根节点的值进行比较,如果相等就返回,如果小于就到左子树中递归查找,如果大于就到右子树中递归查找。

代码实现:

首先定义二叉树的数据结构

public class Node {
    private int value;
    private Node left;
    private Node right;
    
    public Node(){
        
    }
    public Node(Node left,Node right,int value){
        this.left=left;
        this.right=right;
        this.value=value;
    }
    public Node(int value){
        this(null,null,value);
    }

    public int getValue() {
        return this.value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public Node getLeft() {
        return this.left;
    }

    public void setLeft(Node left) {
        this.left = left;
    }

    public Node getRight() {
        return this.right;
    }

    public void setRight(Node right) {
        this.right = right;
    }
}

如上代码定义了二叉排序树的数据结构Node,在Node中包含的value、left、right分别表示二叉排序树的值、左子节点、右子节点。

并有相应的get set方法

(2)定义二叉树的插入方法:

   public void insertBST(int key){
        //设置一个父节点
        Node p =root;
        //prev 是待插入节点的父节点
        Node prev=null;
        
        while (p!=null){
            prev=p;
            if (key<p.getValue()){
                p=p.getLeft();
            }
            else if(key>p.getValue()){
                p=p.getRight();
            }
            else {
                return;
            }
        }
        //最终决定插入哪里
        if (root==null){
            root=new Node(key);
        }
        else if(key< prev.getValue()){
            prev.setLeft(new Node(key));
        }
        else {
            prev.setRight(new Node(key));
        }
    }

如上代码定义了insertBST()来向二叉排序树中插入节点,具体操作分 4步:①循环查找需要插入的节点prev;②如果二叉树的根节点为null,则说明二叉树是空树,直接将该节点设置为根节点;③如果待插入的数据小于该节点的值,则将其插入该节点的左节点;④如果待插入的数据大于该节点的值,则将其插入该节点的右节点。

(3)定义二叉排序树的删除方法:

   /**
     * 删除二叉树中的节点
     * 分为三种情况:(删除节点为*p,其父节点为*f)
     * (1)要删除的*p节点是叶子节点,只需要修改它的双亲节点的指针为空
     * (2)若*p只有左子树或者只有右子树,则直接让左子树或者右子树代替*p
     * (3)若*p又有左子树,又有右子树
     *         则用p左子树中的最大的值(即最右端S)代替P,删除S,重接其左子树
     */
    public void deleteBST(int key){
        deleteBST(root,key);
    }

    private boolean deleteBST(Node node,int key){
        if (node==null){
            return false;
        }else {
            if(key==node.getValue()){
                delete(node);
            }else if(key<node.getValue()){
                return deleteBST(node.getLeft(),key);
            }else {
                return deleteBST(node.getRight(),key);
            }
        }
    }

    private boolean delete(Node node){
        Node temp =null;
        /**
         * 右子树为空,那么就重接他的左子树
         * 如果是叶子节点,那么就删除了
         */
        
        if(node.getRight()==null){
            temp=node;
            node=node.getLeft();
        }
        //左子树空,重接他的右子树
        else if (node.getLeft()==null){
            temp=node;
            node=node.getRight();
        }
        //左右都不空
        else{
            temp=node;
            Node s =node;
            //转向左子树,让其向右走到尽头
            s=s.getLeft();
            while(s.getRight()!=null){
                temp=s;
                s=s.getRight();
            }
            node.setValue(s.getValue());
            if (temp!=node){
                temp.setRight(s.getLeft());
            }else {
                temp.setLeft(s.getLeft());
            }
        }
        return true;
    }

以上代码通过三种方法实现了二叉树的删除,deleteBST(int key)是提供给用户的删除方法,会调deleteBST(Node node, int key),其中Node参数为根节点,表示从根节点开始递归查找和删除;deleteBST(Node node, int key)通过递归查找找到要删除的节点。查找要删除的节点的具体做法如下。
◎ 如果key和当前节点的值相等,则说明找到了需要删除的节点。
◎ 如果key小于当前节点的值,则在左子树中查找。
◎ 如果key大于当前节点的值,则在右子树中查找。
在找到要删除的节点后,调用delete(Node node)删除该节点,这里的删除分3种情况。
◎ 如果右子树为空,则只需将它的左子树接到该节点。
◎ 如果右子树为空,则只需将它的右子树接到该节点。
◎ 如果左右子树均不为空,则需要在左子树中寻找最小的节点,并将左子树中最小的节点接到当前节点。
(4)定义二叉排序树的查询方法:

  /**
     * 
     * 查找二叉排序树是否有key值
     */
    public boolean searchBST(int key){
        Node current =root;
        while(current !=null){
            //等于当前值则查找成功
            if(key==current.getValue()){
                return true;
            }
            //若小于 左子树查找
            else if(key<current.getValue()){
                current=current.getLeft();
            }else {   //反之,右子树查找
                current=current.getRight();
            }
        }
        return false;
    }

以上代码定义了searchBST()用于查询二叉排序树,具体做法如下。
◎ 如果key和当前节点的值相等,则说明找到了该节点。
◎ 如果key小于当前节点的值,则在左子树中查找。
◎ 如果key大于当前节点的值,则在右子树中查找。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你们卷的我睡不着QAQ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值