BST 二叉搜索树 (binary Search Tree )[一]

简介

二叉搜索树是一种特殊的二叉树 在我看来感觉象将二分查找图像化.
满足以下条件 :

  • 每个节点最多有两个孩子
  • 每个节点的值,都大于左孩子,而小于右孩子

特点

在这里插入图片描述

  1. 首先在每一层上二叉树的节点最大为 2^(i-1) (i为层数).
  2. 二叉树的深度为k = [log2(n)]+1(n为总的节点个数).

代码

BSTNode

值得注意的是 :

  • get和set方法直接生成就好
  • 定义左右孩子时将泛型写上
class BSTNode<T extends Comparable<T>> {
   // 节点的数据域
   private T data;
   // 节点的左孩子域
   private BSTNode<T> left;
   // 节点的右孩子域
   private BSTNode<T> right;

   public BSTNode(T data, BSTNode<T> left, BSTNode<T> right) {
       this.data = data;
       this.left = left;
       this.right = right;
   }

   public T getData() {
       return data;
   }

   public void setData(T data) {
       this.data = data;
   }

   public BSTNode getLeft() {
       return left;
   }

   public void setLeft(BSTNode<T> left) {
       this.left = left;
   }

   public BSTNode getRight() {
       return right;
   }

   public void setRight(BSTNode<T> right) {
       this.right = right;
   }
}

BSTree初始化 :

类型擦除

class BSTree<T extends Comparable<T>> {
   // 构建指向树根的节点 
   private BSTNode<T> root;

   /**
    * BST树的初始化
    */
   public BSTree() {
       this.root = null;
   }
}

insert() : 构建二叉搜索树

此处添加了parent节点保存在cur为null时的父亲节点 ,用于最后添加新节点

  public void non_insert(T data) {
 if (root == null) {  // 添加根节点 
           root = new BSTNode<>(data, null, null);
       }
// 搜索BST树,找到data合适的插入位置
       BSTNode<T> parent = null;
       BSTNode<T> cur = this.root;

       while(cur != null){
           parent = cur;
           if(cur.getData().compareTo(data) < 0){  // cur.data < data ,找其右节点
               cur = cur.getRight();
           } else if(cur.getData().compareTo(data) > 0){  // cur.data > data ,找其左节点
               cur = cur.getLeft();
           } else {
               return;
           }
//构建data的节点,并将节点其父亲节点相应的地址域中 
 if(parent.getData().compareTo(data) < 0){
           parent.setRight(new BSTNode<>(data, null, null));
       } else {
           parent.setLeft(new BSTNode<>(data, null, null));
       }
}

remove():非递归的删除

操作次序

  1. 先找到要删除的元素的位置,此处和insert一样,用parent节点作为最后删除的依赖
  2. 然后根据该元素节点的情况再进行对应的操作


    该元素节点可能出现的情况
    在这里插入图片描述
    1.含有两个节点的情况(1.左右孩子)
    eg : 此时删除data = 43节点时,想保证二叉树的顺序性,必须满足大于23 并且小于52的data值的节点
    主要思想:找到删除节点的前驱节点或者后继节点,用前驱节点或者后继节点的值把当前的节点的值把当前的节点的值覆盖,直接将前驱节点或者后继节点删除即可
    前驱节点: 待删节点左子树中值最大的节点
    后继节点: 待删节点右子树中值最小的节点
    2.节点有一个孩子
    3.节点没有孩子
    2,3可看为同一种情况,把删除节点的孩子,写入父节点相应的地址域中
/**
     * BST树的非递归删除操作
     * @param data
     */
    public void non_remove(T data){
        //1. 先搜索值为data的待删除节点
        if(this.root == null){
            return;
        }

        BSTNode<T> parent = null; // parent = root
        BSTNode<T> cur = this.root;
        while(cur != null){
            if(cur.getData().compareTo(data) > 0){
                parent = cur;
                cur = cur.getLeft();
            } else if(cur.getData().compareTo(data) < 0){
                parent = cur;
                cur = cur.getRight();
            } else {
                break;
            }
        }

        // BST中不存在值为data的节点
        if(cur == null){
            return;
        }

        //2.处理有两个孩子的待删除节点情况
        if(cur.getLeft() != null && cur.getRight() != null){
            BSTNode<T> old = cur;
            parent = cur;
            cur = cur.getLeft();  //获取其左节点
//此处当左节点没有最右节点时,可以直接将左节点覆盖
            while(cur.getRight() != null){  // 获取其左节点的最右节点
                parent = cur;
                cur = cur.getRight();
            }

            old.setData(cur.getData());
        }

        //3.删除有一个孩子的或者没有孩子的节点  cur
        BSTNode<T> child = cur.getLeft();
        if(child == null){
            child = cur.getRight();
        }

        // data  parent.getData()
        if(parent == null){ // 表示删除的是根节点
            this.root = child;
        } else {
            if(cur == parent.getLeft()){ // 把cur的child写入父节点的左孩子域
                parent.setLeft(child);
            } else { // 把cur的child写入父节点的右孩子域
                parent.setRight(child);
            }
        }
    }

遍历

/**
     * 前序遍历递归实现
     * @param root
     */
    private void preOrder(BSTNode<T> root) {
        if(root != null){
            System.out.print(root.getData() + " "); // V
            preOrder(root.getLeft()); // L
            preOrder(root.getRight()); // R
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值