willjava

导航

 
package com.datastructure.tree;


public class BinarySearchTree<T extends Comparable<? super T>> {

    static class BinaryNode<T> {
        T data;
        BinaryNode<T> left;
        BinaryNode<T> right;
        
        public BinaryNode() {
            this(null, null, null);
        }
        
        
        public BinaryNode(T data) {
            this(data, null, null);
        }

        public BinaryNode(T data, BinaryNode<T> left, BinaryNode<T> right) {
            super();
            this.data = data;
            this.left = left;
            this.right = right;
        }
        
    }
    
    
    private BinaryNode<T> rootTree = null;
    
    public BinarySearchTree() {
    }
    
    public boolean isEmpty() {
        return rootTree == null;
    }
    
    /**
     * 查找操作
     *  在二叉查找树中查找key的过程如下:
         1、若二叉树是空树,则查找失败。
         2、若key等于根结点的数据,则查找成功,否则,
         3、若key小于根结点的数据,则递归查找其左子树,否则,
         4、递归查找其右子树。
     */
    public boolean contains(T key) {
        return contains(rootTree, key);
    }
    
    public boolean contains(BinaryNode<T> node, T key) {
        if(null == node) { //二叉树是空树,则查找失败。
            return false;
        }
        int result = key.compareTo(node.data);
        
        if(result < 0) { // 若key小于根结点的数据,则递归查找其左子树
            return contains(node.left, key);
        } else if(result > 0) { // 若key大于根结点的数据,则递归查找其右子树
            return contains(node.right, key);
        } else { //若key等于根结点的数据,则查找成功
            return true;
        }
    }
    
    /**
     * 查找最小值
     *  最左子树的值
     */
    public T findMin() {
        if(isEmpty()) return null;
        
        return findMin(rootTree).data;
    }
    
    public BinaryNode<T> findMin(BinaryNode<T> node) {
        if(null == node)
            return null;
        if(null == node.left) 
            return node;
        return findMin(node.left);
    }
    
    /**
     * 查找最大值
     *  最右子树的值
     */
    public T findMax() {
        if(isEmpty()) return null;
        
        return findMax(rootTree).data;
    }
    
    public BinaryNode<T> findMax(BinaryNode<T> node) {
        if(null == node)
            return null;
        if(null == node.right) 
            return node;
        return findMin(node.right);
    }
    
    /**
    * 二叉树查找树b插入操作key的过程如下:
        1、若b是空树,则直接将插入的结点作为根结点插入。
        2、key等于b的根结点的数据的值,则直接返回,否则。
        3、若key小于b的根结点的数据的值,则将key要插入的结点的位置改变为b的左子树,否则。
        4、将key要插入的结点的位置改变为b的右子树。
    */
    public void insert(T key) {
        rootTree = insert(rootTree, key);
    }
    
    public BinaryNode<T> insert(BinaryNode<T> node, T key) {
        if(null == node) {
            return new BinaryNode<T>(key);
        }
        int result = key.compareTo(node.data);
        
        if(result < 0) {
            node.left = insert(node.left, key);
        } else if(result > 0) {
            node.right = insert(node.right, key);
        } else
            ;
        
        return node;
        
    }
    
    /**
     * 删除操作
                         对于二叉查找树的删除操作(这里根据值删除,而非结点)分三种情况:
                   不过在此之前,我们应该确保根据给定的值找到了要删除的结点,如若没找到该结点
                   不会执行删除操作!
                   
      1、  如果结点为叶子结点(没有左、右子树),此时删除该结点不会破坏树的结构, 直接删除,修改其父结点指向它的引用为null
      2. 如果其结点只包含左子树/右子树的话,此时直接删除该结点,并将其左子树/右子树设置为其父结点的左子树/右子树。即将该结点赋值为其左子树/右子树
      3. 当结点的左右子树都不空的时候,一般的删除策略是用其右子树的最小数据(容易找到)代替要删除的结点数据并递归删除该结点(此时为null),因为 右子树的最小结点不可能有左孩子,所以第二次删除较为容易。
                   
     */
    public void remove(T key) {
        rootTree = remove(rootTree, key);
    }
    
    public BinaryNode<T> remove(BinaryNode<T> node, T key) {
        if(null == node) // 未找到删除结点, 返回null
            return null;
        
        int result = key.compareTo(node.data);
        if(result < 0) { // 递归从左子树删除该元素
            node.left = remove(node.left, key);
        } else if(result > 0) { // 递归从右子树删除该元素
            node.right = remove(node.right, key);
        } else { // 找到该元素,判断左右子树情况
            if(null != node.left && null != node.right) { // 左右子树都不空的时, 将该结点的值替换为右子树的最小值(不存在左子树),然后从右子树中删除该替换的值
                node.data = findMin(node.right).data;
                node.right = remove(node.right, node.data);
            } else { // 如果结点为叶子结点(没有左、右子树)或如果其结点只包含左子树/右子树的话,将该结点赋值为其左子树/右子树
                node = (node.left != null) ? node.left : node.right;
            }
        }
        
        return node;
    }
    
}

 

posted on 2016-04-29 14:21  威尔爪哇  阅读(210)  评论(0编辑  收藏  举报