二叉查找树的简单实现

二叉查找树首先也是个二叉树,符合二叉树的一切特点。

原文地址:http://blog.csdn.net/qq_25806863/article/details/74638590

简单介绍

但是二叉查找树要求对树中的每个节点,这个节点的左子树中所有的值要小于自己,右子树中所有的值要大于自己。

下面是两个的区别:

二叉查找树:
这里写图片描述

不是二叉查找树:
这里写图片描述

简单实现

主要是查询,插入和删除的方法

public class MySearchTree<E extends Comparable<E>> {

    private BinaryNode<E> root;

    public MySearchTree() {
        root = null;
    }

    public void makeEmpty() {
        root = null;
    }

    public boolean isEmpty() {
        return root == null;
    }

    public boolean contains(E x) {
        return contains(x, root);
    }

    public E findMin() {
        return findMin(root).element;
    }

    public E findMax() {
        return findMax(root).element;
    }

    public void insert(E x) {
        root =  insert(x, root);
    }

    public void remove(E x) {
        remove(x, root);
    }

    public void printTree() {
        printTree(root);
    }


    /**
     * 如果这个树上的值就是要查找的x,返回true
     * 如果树为空,说明不存在这个值,返回false
     * 如果x小于这个树上的值,就在这个树的左子树上递归查找
     * 如果x大于这个树上的值,就在这个树的右子树上递归查找
     */
    private boolean contains(E x, BinaryNode<E> tree) {
        if (tree == null) {
            return false;
        }
        int compareResult = x.compareTo(tree.element);
        if (compareResult < 0) {
            return contains(x, tree.left);
        } else if (compareResult > 0) {
            return contains(x, tree.right);
        } else {
            return true;
        }
    }


    /**
     * 只要有左子树就一直往左找,左子树为空说明这个就是最小值
     */
    private BinaryNode<E> findMin(BinaryNode<E> tree) {
        if (tree == null) {
            return null;
        } else if (tree.left == null) {
            return tree;
        } else {
            return findMin(tree.left);
        }

    }

    /**
     * 只要有右子树就一直往左找,右子树为空说明这个就是最大值
     */
    private BinaryNode<E> findMax(BinaryNode<E> tree) {
        if (tree == null) {
            return null;
        } else if (tree.right == null) {
            return tree;
        } else {
            return findMax(tree.right);
        }
    }

    /**
     * 如果要插入的树是null,说明这个就是要插入的值该放的位置,new一个子树,绑定到对应的父亲上
     * 如果树不为null,说明这个树上有值,拿x和这个值进行比较
     * 如果两个值相等,说明已经有这个值了,可以进行一些处理
     * 如果x小于树上的值,就往该树的左子树上递归插入
     * 如果x大于树上的值,就往该树的右子树上递归插入
     */
    private BinaryNode<E> insert(E x, BinaryNode<E> tree) {
        if (tree == null) {
            return new BinaryNode<E>(x, null, null);
        }
        int compareResult = x.compareTo(tree.element);
        if (compareResult < 0) {
            tree.left= insert(x, tree.left);
        } else if (compareResult > 0) {
            tree.right =  insert(x, tree.right);
        } else {
            //说明已经有这个值了。
            System.out.println("已经有这个值了");
        }
        return tree;
    }


    /**
     * 比较x和树的值
     * 如果x小于树的值,在树的左子树中递归删除
     * 如果x大于树的值,在树的右子树中递归删除
     * 如果x等于树的值,那么这个值就是要删除的值。
     * 因为删除一个值就要对树进行重新排列,所以这个位置上不能空。
     * 如果这个树只有一个子树,那么就直接把这个子树放在这个位置上
     * 如果这个树有两个子树,那么需要找到右子树的最小值,将这个最小值赋值在要删除的位置上,
     * 然后递归调用从右子树中删除刚刚找到的这个最小值
     */
    private BinaryNode<E> remove(E x, BinaryNode<E> tree) {
        if (tree == null) {
            //没有这个树
            return tree;
        }
        int compareResult = x.compareTo(tree.element);
        if (compareResult < 0) {
            tree.left = remove(x, tree.left);
        } else if (compareResult > 0) {
            tree.right = remove(x, tree.right);
        } else if (tree.left != null && tree.right != null) {
            tree.element = findMin(tree.right).element;
            tree.right = remove(tree.element, tree.right);
        } else {
            tree = (tree.left != null) ? tree.left : tree.right;
        }
        return tree;

    }

    private void printTree(BinaryNode<E> tree) {
        if (tree == null) {
            return;
        }
        System.out.print(tree.element+" ");
        printTree(tree.left);
        printTree(tree.right);

    }

    public static class BinaryNode<E> {
        E element;
        BinaryNode<E> left;
        BinaryNode<E> right;

        public BinaryNode(E element) {
            this(element, null, null);
        }

        public BinaryNode(E element, BinaryNode<E> left, BinaryNode<E> right) {
            this.element = element;
            this.left = left;
            this.right = right;
        }
    }
}

实现的缺点

在代码中,注意remove方法中的一段代码:

else if (tree.left != null && tree.right != null) {
    tree.element = findMin(tree.right).element;
    tree.right = remove(tree.element, tree.right);

这里对删除的处理是,找到右子树中的最小值,把这个最小值放在当前节点上,然后从右子树中删除这个值。

而在insert的时候,是根据比较而随机的插入在左右子树上的。

所以如果交叉调用insert和remove很多次的话,这个二叉树会变得很不平衡,即左右子树的高度差很大。

这种平衡的二叉查找树叫平衡查找树

一个最古老的平衡查找树是AVL树

参考《数据结构与算法分析java版》

猜你喜欢

转载自blog.csdn.net/qq_25806863/article/details/74638590