java 数据结构 二叉查找树的简单实现

什么是二叉查找树

二叉查找树是一种树结构。首先是二叉树。它表示每个节点最多有两个子节点,而二叉查找树,它还要求左子节点必须比右子节点小。
这里写图片描述

对于这个结构,我们以下几个操作的实现:

树中的元素必须能比较

这里的比较,我们不用equals和==,我们要判断它与节点中元素的大小关系,所以这里我们有2种实现方案:
1. 元素实现Comparable接口,重写它的compareTo方法
2. 在二叉树的构造方法中传入特定的Comparator比较器进行比较

    /**
     * 比较器
     */
    private Comparator<T> comparator;

    public BinarySearchTree() {
        root = null;
        comparator = null;
    }

    /**
     * 带有指定比较器的构造方法
     * @param comparator
     */
    public BinarySearchTree(Comparator<T> comparator) {
        root = null;
        this.comparator = comparator;
    }

    /**
     * 自己实现一个compare方法
     * 如果在构造时传入了相应的比较器,则用传入比较器的compare方法
     * 若没有传,则强转成comparable进行比较
     *
     * @param t1
     * @param t2
     * @return
     */
    private int compare(T t1, T t2) {
        /**
         * 如果比较器不为null
         */
        if (comparator != null) {
            return comparator.compare(t1, t2);
        }
        return ((Comparable) t1).compareTo(t2);
    }

insert操作

当执行插入操作时,思路就是比较插入元素和节点元素的大小,若插入元素大,则往节点右边走,相反则往节点左边走,最后当节点的左边或右边为null的时候,就把元素插入进去了.若碰到插入元素重复的情况则不管

    public void insert(T t) {
        root = insert(t, root);
    }

    private BinaryNode<T> insert(T t, BinaryNode binaryNode) {
        if (binaryNode == null) {
            BinaryNode node = new BinaryNode(t, null, null);
            return node;
        }
        Object element = binaryNode.element;

        int compare = compare(t, (T) element);

        if (compare == -1) {
            // 说明t 比 element 小
            binaryNode.left = insert(t, binaryNode.left);
        } else if (compare == 1) {
            // 说明t 比 element 大
            binaryNode.right = insert(t, binaryNode.right);
        } else ;
        /**
         * 若t和element一样大则不做任何事情
         */

        /**
         * 把根返回
         */
        return binaryNode;
    }

contains操作

和insert操作基本一个思路,就是比较元素和节点元素大小来判断往左走还是往右走,若碰到元素和节点元素相等的情况则返回true,否则返回false

    public boolean contains(T t) {
        return contains(t, root);
    }

    private boolean contains(T t, BinaryNode binaryNode) {
        if (binaryNode == null) {
            return false;
        }
        Object element = binaryNode.element;

        int compare = compare(t, (T) element);

        if (compare == 1) {
            return contains(t, binaryNode.right);
        } else if (compare == -1) {
            return contains(t, binaryNode.left);
        } else {
            return true;
        }
    }

findMin和findMax操作

很简单,findMin就是一直往左走,知道节点的左节点为null时,则该节点的元素最小,findMax则相反,这里我们findMax用递归实现,findMin用循环实现

    public T findMin() {
        BinaryNode min = findMin(root);
        if (min != null) {
            return (T) min.element;
        }
        return null;
    }

    public T findMax() {
        BinaryNode max = findMax(root);
        if (max != null) {
            return (T) max.element;
        }
        return null;
    }

    private BinaryNode findMin(BinaryNode binaryNode) {
        if (binaryNode != null) {
            while (binaryNode.left != null) {
                binaryNode = binaryNode.left;
            }
        }
        return binaryNode;
    }

    private BinaryNode findMax(BinaryNode binaryNode) {
        if (binaryNode == null) {
            return null;
        }
        if(binaryNode.right != null) {
            return findMax(binaryNode.right);
        }
        return binaryNode;
    }

remove操作

这个比较麻烦,因为有几种情况:

  • 删除的节点没有子节点。。。。这个比较简单,直接删除即可
  • 删除的节点有一个子节点。。。。我们通过把要删除节点的父节点的链绕过该节点,在删除
  • 删除的节点有两个子节点。。。这种情况就比较麻烦了,我们先拿到这个节点的右子节点,然后一直往左拿到最小的那个节点,用这个最小节点的数据代替我们要删除的节点,然后把这个最小的节点删除即可
 public boolean remove(T t) {
        BinaryNode remove = remove(t, root);
        if (remove != null) {
            return true;
        }
        return false;
    }

    private BinaryNode remove(T t, BinaryNode binaryNode) {
        if (binaryNode == null) {
            return binaryNode;
        }
        int compare = compare(t, (T) binaryNode.element);

        if (compare == -1) {
            binaryNode.left = remove(t, binaryNode.left);
        } else if (compare == 1) {
            binaryNode.right = remove(t, binaryNode.right);
        } else if (binaryNode.left != null && binaryNode.right != null) {
       /**
        *这儿注释的三局代码,findMin会搜索一遍,remove又会搜索一遍,所以我们写一个特殊的removeMin方法来避免这个操作
        */
//            BinaryNode min = findMin(binaryNode.right);
//            binaryNode.element = min.element;
//            binaryNode.right = remove((T) min.element, binaryNode.right);
            removeMin(binaryNode);
        } else {
            binaryNode = binaryNode.left == null ? binaryNode.right : binaryNode.left;
        }
        return binaryNode;
    }

    private void removeMin(BinaryNode binaryNode) {
        if (binaryNode == null) {
            return ;
        }
        BinaryNode node = binaryNode.right;
        BinaryNode parentNode = null;

        while (true) {
            if(node.left != null) {
                parentNode = node;
                node = node.left;
            } else {
                Object element = node.element;
                binaryNode.element = element;
                parentNode.left = node.right;
                break;
            }
        }
    }

代码

package collection;

import java.util.Comparator;

/**
 * Created by sunhan on 2018/1/14.
 */
public class BinarySearchTree<T> {


    private static class BinaryNode<T> {

        private BinaryNode<T> left;

        private BinaryNode<T> right;

        private T element;

        public BinaryNode(T t) {
            this(t, null, null);
        }

        public BinaryNode(T t, BinaryNode left, BinaryNode right) {
            this.element = t;
            this.left = left;
            this.right = right;
        }
    }


    /**
     * 先序遍历
     */

    public void suffix(){
        midIterator(root);
    }

    private void suffixIterator(BinaryNode node){
        System.out.println(node.element.toString());
        if(node.left != null){
            suffixIterator(node.left);
        }
        if(node.right != null){
            suffixIterator(node.right);
        }
    }

    /**
     * 中序遍历
     */

    public void mid(){
        midIterator(root);
    }

    private void midIterator(BinaryNode node){
        if(node.left != null){
            midIterator(node.left);
        }
        System.out.println(node.element.toString());
        if(node.right != null){
            midIterator(node.right);
        }
    }

    /**
     * 后序遍历
     */

    public void back(){
        backIterator(root);
    }

    private void backIterator(BinaryNode node){
        if(node.left != null){
            backIterator(node.left);
        }
        if(node.right != null){
            backIterator(node.right);
        }
        System.out.println(node.element.toString());
    }

    /**
     * 根
     */
    private BinaryNode<T> root;

    /**
     * 比较器
     */
    private Comparator<T> comparator;

    public BinarySearchTree() {
        root = null;
        comparator = null;
    }

    /**
     * 带有指定比较器的构造方法
     * @param comparator
     */
    public BinarySearchTree(Comparator<T> comparator) {
        root = null;
        this.comparator = comparator;
    }

    /**
     * 自己实现一个compare方法
     * 如果在构造时传入了相应的比较器,则用传入比较器的compare方法
     * 若没有传,则强转成comparable进行比较
     *
     * @param t1
     * @param t2
     * @return
     */
    private int compare(T t1, T t2) {
        /**
         * 如果比较器不为null
         */
        if (comparator != null) {
            return comparator.compare(t1, t2);
        }
        return ((Comparable) t1).compareTo(t2);
    }

    public void insert(T t) {
        root = insert(t, root);
    }

    private BinaryNode<T> insert(T t, BinaryNode binaryNode) {
        if (binaryNode == null) {
            BinaryNode node = new BinaryNode(t, null, null);
            return node;
        }
        Object element = binaryNode.element;

        int compare = compare(t, (T) element);

        if (compare == -1) {
            // 说明t 比 element 小
            binaryNode.left = insert(t, binaryNode.left);
        } else if (compare == 1) {
            // 说明t 比 element 大
            binaryNode.right = insert(t, binaryNode.right);
        } else ;
        /**
         * 若t和element一样大则不做任何事情
         */

        /**
         * 把根返回
         */
        return binaryNode;
    }

    public T findMin() {
        BinaryNode min = findMin(root);
        if (min != null) {
            return (T) min.element;
        }
        return null;
    }

    public T findMax() {
        BinaryNode max = findMax(root);
        if (max != null) {
            return (T) max.element;
        }
        return null;
    }

    private BinaryNode findMin(BinaryNode binaryNode) {
        if (binaryNode != null) {
            while (binaryNode.left != null) {
                binaryNode = binaryNode.left;
            }
        }
        return binaryNode;
    }

    private BinaryNode findMax(BinaryNode binaryNode) {
        if (binaryNode == null) {
            return null;
        }
        if(binaryNode.right != null) {
            return findMax(binaryNode.right);
        }
        return binaryNode;
    }

    public boolean contains(T t) {
        return contains(t, root);
    }

    private boolean contains(T t, BinaryNode binaryNode) {
        if (binaryNode == null) {
            return false;
        }
        Object element = binaryNode.element;

        int compare = compare(t, (T) element);

        if (compare == 1) {
            return contains(t, binaryNode.right);
        } else if (compare == -1) {
            return contains(t, binaryNode.left);
        } else {
            return true;
        }
    }

    public boolean remove(T t) {
        BinaryNode remove = remove(t, root);
        if (remove != null) {
            return true;
        }
        return false;
    }

    private BinaryNode remove(T t, BinaryNode binaryNode) {
        if (binaryNode == null) {
            return binaryNode;
        }
        int compare = compare(t, (T) binaryNode.element);

        if (compare == -1) {
            binaryNode.left = remove(t, binaryNode.left);
        } else if (compare == 1) {
            binaryNode.right = remove(t, binaryNode.right);
        } else if (binaryNode.left != null && binaryNode.right != null) {
//            BinaryNode min = findMin(binaryNode.right);
//            binaryNode.element = min.element;
//            binaryNode.right = remove((T) min.element, binaryNode.right);
            removeMin(binaryNode);
        } else {
            binaryNode = binaryNode.left == null ? binaryNode.right : binaryNode.left;
        }
        return binaryNode;
    }

    private void removeMin(BinaryNode binaryNode) {
        if (binaryNode == null) {
            return ;
        }
        BinaryNode node = binaryNode.right;
        BinaryNode parentNode = null;

        while (true) {
            if(node.left != null) {
                parentNode = node;
                node = node.left;
            } else {
                Object element = node.element;
                binaryNode.element = element;
                parentNode.left = node.right;
                break;
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值