二叉搜索树(一)二叉搜索树的概念与实现add方法、简单打印

二叉搜索树的优势

如果要在n个整数中搜索某个整数,查看其是否存在。
(1)假如使用动态存放元素,从第0个位置开始遍历搜索,平均时间复杂度为O(n)。
(2)假如维护一个有序的动态数组,使用二分查找,最坏时间复杂度是O(lngn)。但是添加和删除的时间复杂度仍然是O(n)。
(3)使用二叉搜索树,添加、删除、搜索的最坏时间复杂度均可优化至O(logn)。

二叉搜索树的概念

在这里插入图片描述

(一)二叉搜索树是二叉树的一种,是应用非常广泛的一种二叉树,英文简称为 BST。

  • 二叉搜索树又被称为二叉查找树、二叉排序树。
  • 任意一个节点的值都大于左子树的所有节点值。
  • 任意一个节点的值都小于右子树的所有节点值。

(二)二叉搜索树可以大大提高搜索数据的效率。

(三)二叉搜索树存储的元素必须具备可比较性。

  • 比如int、short、double等。
  • 如果是自定义类型,则需要指定比较方法。
  • 不允许为null。

接口设计

方法声明功能介绍
int size()元素的数量
boolean isEmpty()是否为空
boolean contains()是否包含
void clear()清空
void add(Node< E > node)添加节点
void remove(Node< E > node删除节点
public class BinarySearchTree<E>{
    //节点类
    private class Node<E>{
        E element;
        Node<E> left;
        Node<E> right;
        Node<E> parent;
        public Node(E element,Node<E> parent){
            this.element=element;
            this.parent=parent;
        }
    }
    //根节点
    private Node<E> root;
    int size;

    public BinarySearchTree() {
    }

    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size==0;
    }

    public boolean contains(E element) {
        return false;
    }

    public void clear() {

    }

    public void add(E element) {
  
    }

   
    public void remove(E element) {

    }
}

add接口的实现

在进行添加操作时,必须对将要添加的节点元素与树上节点的元素进行比较,才能找到正确的放置位置,而不同的元素(可能是自定义类对象)需要有不同的比较方法,相同的元素在不同的场合也需要不同的比较方法。那么我们可以通过创建一个Comparator类型的引用,并在二叉搜索的构造方法中通过匿名内部类传入,使用它的compare方法就可以实现不同的比较方法,此外,若是不想传入comparator,则可在比较时将比较元素强转为Comparable接口类型(需要让元素实现Comparable接口,否则运行报错,且Integer等包装类已实现该接口),调用compareTo方法进行比较。

private Comparator<E> comparator;

public BinarySearchTree() {
}
//传入Comparator对象,用于比较
public BinarySearchTree(Comparator<E> comparator) {
    this.comparator = comparator;
}

/**
* 用于进行元素的比较
* @param e1
* @param e2
* @return
*/
private int compareTo(E e1,E e2){
   //如果比较器不为空,则使用比较器
   if(null!=comparator){
       return comparator.compare(e1,e2);
   }else {//否则要求实现Comparable接口的compareTo方法
       return ((Comparable)e1).compareTo(e2);
   }
}

可以进行比较后则可完成add方法了,简单地说就是比较元素大小,寻找添加位置。

public void add(E element) {
        //如果是第一个节点
        if(size==0) {
            root = new Node(element, null);
            size++;
            return;
        }
        //否则对元素进行比较找到放置的位置
        Node<E> node=root,par=null;//记录父节点
        int cmp=0;//保存比较大小
        while(node!=null){
            par=node;
            cmp=compareTo(element,node.element);
            //若元素小于当前节点
            if(cmp<0){
                node=node.left;
            }else if(cmp>0){
                node=node.right;
            }else {//相同覆盖
                node.element=element;
                return ;
            }
        }
        //此时找到插入位置
        if(cmp<0){
            par.left=new Node(element,par);
        }else{
            par.right=new Node(element,par);
        }
        size++;
    }

进行简单的打印

在此通过先序遍历访问所有节点,对字符串进行拼接,然后打印。

@Override
public String toString() {//实现二叉树的简单打印
    StringBuilder sb=new StringBuilder();
    toString(root,sb,"");
    return sb.toString();
}

/**
 * 通过先序遍历的顺序拼接字符
 * @param node
 * @param sb
 * @param preStr 需要在节点前拼接的字符
 */
private void toString(Node<E> node,StringBuilder sb,String preStr){
    if(null==node)return;
    //处理元素,拼接字符
    sb.append(preStr).append(node.element).append('\n');
    toString(node.left,sb,preStr+"left---");
    toString(node.right,sb,preStr+"right--");
}

整体代码


import java.util.Comparator;

public class BinarySearchTree<E>{
    //节点类
    private class Node<E>{
        E element;
        Node<E> left;
        Node<E> right;
        Node<E> parent;
        public Node(E element,Node<E> parent){
            this.element=element;
            this.parent=parent;
        }
    }
    //根节点
    private Node<E> root;
    int size;
    private Comparator<E> comparator;

    public BinarySearchTree() {
    }
    //传入Comparator对象,用于比较
    public BinarySearchTree(Comparator<E> comparator) {
        this.comparator = comparator;
    }

    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size==0;
    }

    public boolean contains(E element) {
        return false;
    }

    public void clear() {

    }

    public void add(E element) {
        //如果是第一个节点
        if(size==0) {
            root = new Node(element, null);
            size++;
            return;
        }
        //否则对元素进行比较找到放置的位置
        Node<E> node=root,par=null;//记录父节点
        int cmp=0;//保存比较大小
        while(node!=null){
            par=node;
            cmp=compareTo(element,node.element);
            //若元素小于当前节点
            if(cmp<0){
                node=node.left;
            }else if(cmp>0){
                node=node.right;
            }else {//相同覆盖
                node.element=element;
                return ;
            }
        }
        //此时找到插入位置
        if(cmp<0){
            par.left=new Node(element,par);
        }else{
            par.right=new Node(element,par);
        }
        size++;
    }

    public void remove(E element) {

    }

    /**
     * 用于进行元素的比较
     * @param e1
     * @param e2
     * @return
     */
    private int compareTo(E e1,E e2){
        //如果比较器不为空,则使用比较器
        if(null!=comparator){
            return comparator.compare(e1,e2);
        }else {//否则要求实现Comparable接口的compareTo方法
            return ((Comparable)e1).compareTo(e2);
        }
    }

    @Override
    public String toString() {//实现二叉树的简单打印
        StringBuilder sb=new StringBuilder();
        toString(root,sb,"");
        return sb.toString();
    }

    /**
     * 通过先序遍历的顺序拼接字符
     * @param node
     * @param sb
     * @param preStr 需要在节点前拼接的字符
     */
    private void toString(Node<E> node,StringBuilder sb,String preStr){
        if(null==node)return;
        //处理元素,拼接字符
        sb.append(preStr).append(node.element).append('\n');
        toString(node.left,sb,preStr+"left---");
        toString(node.right,sb,preStr+"right--");
    }
}

进行测试

public class BSTTest {
    public static void main(String[] args) {
        BinarySearchTree<Integer> bst=new BinarySearchTree<>();
        int[] arr={4,5,6,2,3,9};
        for(int i=0;i<6;i++)
            bst.add(arr[i]);
        System.out.println(bst);
    }
}

输出结果为:
在这里插入图片描述
也就是:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值