数据结构----BST(二叉搜索树增加、删除、查询)

本文介绍了二叉搜索树(BST)的概念,包括其特性:右孩子大于父节点,左孩子小于父节点。讲解了如何通过插入操作构建BST,删除操作的策略分析,以及数据查找的方法。内容详细阐述了每个操作的过程,并提供了操作的逻辑思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、BST(Binary Search Tree):二叉搜索树,将数据的增加、删除、查询的时间复杂度都达到O(log2 n)
  ①所有的非叶子节点至多拥有两个节点(右孩子>父节点的值>左孩子)
  ②所有的节点除过存储自己的数据之外,还包括左孩子和右孩子的信息
  ③每一层节点的个数为 2^n (根节点为0层)–>树的深度为(log2 n)
如下图所示,对一组数进行BST排列:(53,28,82,12,35,69,87,18,47,74,95)
在这里插入图片描述
二、代码实现BST树
①因为每一个节点的类型为在这里插入图片描述

class BSTnode<T extends Comparable<T>>{ //因为要进行比较所以需要对泛型规定上界
    private T data;  //数据域
    private BSTnode<T> left;   //存放左孩子
    private BSTnode<T> right;  //存放右孩子
……
}

②、生成二叉搜索树(数据的插入insert (T data) ):
   1>肯定从根节点(root)开始生成,即第一个插入的数为根节点。

 public void insert(T data){
        //判断root是否为空,生成根节点
        if (root==null){
            this.root=new BSTnode<>(data,null,null);
            return;
        }

   2> 之后插入的数与其比较大于则继续往右孩子查询,小于则继续往左孩子查询
node指向根节点进行遍历,重复步骤 2找到为空的合适插入的位置,parent为要插入位置的父节点

 //如果root不为空,从根节点找到合适位置
        BSTnode<T> node=root;
        BSTnode<T> parent=null;
        while (node!=null) {  //找到合适的位置且为空跳出循环
            if (node.getData().compareTo(data) > 0) { //如果插入元素大于根节点
                parent=node;
                node = node.getLeft();
            }
            else if (node.getData().compareTo(data) < 0){
                parent=node;
                node = node.getRight();
            }
            else { //不允许插入重复的元素
                return;
            }
        }

   3> 重复步骤2直至找到为空的位置,生成新节点并将新节点放置到该位置。
此时已经找到要插入位置的父节点,还需要判断是放置于
                    (1)父节点的左节点(val<父节点.data)
                    (2)父节点的右节点(val>父节点.data)

 //3.生成新节点,把节点的地址,写入父节点相应的地址域
        if (parent.getData().compareTo(data) >0){
            parent.setLeft(new BSTnode<>(data,null,null));
        }
        else if (parent.getData().compareTo(data) < 0){
            parent.setRight(new BSTnode<>(data,null,null));
        }

③、数据的删除(remove (T val) )
思路分析:
(若数据存在)删除的数据分为三种情况:在这里插入图片描述

   1.删除有两个孩子的节点
      找到删除节点的前驱节点或后继节点,用前驱节点或后继节点把
      当前删除节点的值覆盖掉。
   然后直接删除前驱节点或者后继节点---->转换成删除一个节点或删除叶子节点
     ①前驱节点:待删除节点左子树中,值最大的节点
     ②后继节点:待删除节点右子树中,值最小的节点`

在这里插入图片描述

 //1.先找到待删除节点
        BSTnode<T> cur=root;
        BSTnode<T> parent=null;
        while (cur!=null){
            if (cur.getData().compareTo(val)>0){  //删除元素小于当前节点
                parent=cur;
                cur=cur.getLeft();
            }
            else if (cur.getData().compareTo(val)<0){  //删除元素da于当前节点
                parent=cur;
                cur=cur.getRight();
            }
            else{
                break;
            }
        }

此时cur为待删除节点,parent为cur的父节点(相当于上图53,因为后边要进行重写)

  if (cur == null) {   //表示BST树中没有值为val的节点
            return;
        }
        //2.判断节点是否有两个孩子,若有,用前驱代替,直接删除前驱
        if (cur.getRight()!=null&&cur.getLeft()!=null){  //当前节点有两个孩子
            //找到当前节点的前驱节点,从当前位置往下找
            BSTnode<T> old=cur;   //用old保存待删除节点
            parent=cur;
            cur=cur.getLeft();  //找待删除节点的前驱节点
            while (cur.getRight()!=null){
                parent=cur;
                cur=cur.getRight();
            }  
            //此时cur指向前驱节点
            old.setData(cur.getData());   //将前驱节点的值覆盖要删除的节点值
        }

在这里插入图片描述

  //3.删除有一个孩子的节点或者没有孩子的节点(看做有一个孩子,为null),此时cur为前驱节点
             BSTnode<T> child=cur.getLeft(); //先将child指向左孩子
             if (child==null){  //待删除节点没有左孩子或者没有孩子
                 child=cur.getRight();
             }
             if (parent==null){  //删除的为根节点
                 this.root=child;
             }
           //删除的节点有左孩子或者没有孩子,为下图删除28的情况,前驱节点为47,将47放置到28 的位置,则需要删除节点47

在这里插入图片描述

 else {
             if (parent.getLeft()==cur){     
                 parent.setLeft(child);
             }
             else {
                 parent.setRight(child);
             }
         }
    }

③、数据的查找:
    若待查找数据小于根节点,则在左子树查找
    否则,在右子树查找
  重复上述操作,直到查找到返回true;
  若查找到叶子节点还没有找到,返回false;

 public boolean non_query(T val){
        BSTnode<T> cur=root;
        BSTnode<T> parent=null;
        while (cur!=null){
            if (cur.getData().compareTo(val)>0){  //删除元素小于当前节点
                cur=cur.getLeft();
            }
            else if (cur.getData().compareTo(val)<0){  //删除元素da于当前节点
                cur=cur.getRight();
            }
            else {
                return true;
            }
        }
      return false;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值