数据结构(Java)——二叉查找树

有时候,问题很复杂,答案却很简单。 跟生活玩,别太认真了,反正最终没谁能活着离开这场游戏。人生就像舞台,不到谢幕,永远不会知道自己有多精彩。

1.二叉查找树的概述

二叉查找树是带有附加属性的二叉树,即对树中的每个结点,其做孩子都要小于父结点,而父结点又要小于等于其右孩子。
二叉查找数是对二叉树定义的扩展,前面的二叉树的实现 中我们的对二叉树做了一个简单的实现,其中使用BinaryTreeNode类来表示树中每个结点。每个BinaryTreeNode对象要维护一个指向结点所存储元素引用,另外还要维护指向结点的每个孩子的引用。

2.二叉查找树的类图结构

二叉查找树的类图结构

3.二叉查找树链表实现

BinarySearchTreeADT

package ds.java.ch11;
/** 
 * @author LbZhang
 * @version 创建时间:2015年11月24日 上午11:04:13 
 * @description 类说明
 */
public interface BinarySearchTreeADT<T> extends BinaryTreeADT<T>{

    //添加自身具有的方法
    /**
     * 往树中添加一个元素
     * @param element
     */
    public void addElement(T element);
    /**
     * 树中删除一个元素
     * @param element
     */
    public T removeElement(T element);
    /**
     * 往树中删除元素的任何存在
     * @param element
     */
    public void removeAllOccurrences(T targetElement);
    /**
     * 删除最小的元素
     * @param element
     */
    public T removeMin();
    /**
     * 删除最大的元素
     * @param element
     */
    public T removeMax();
    /**  
     * @param element
     */
    public T findMin();
    /**
     * 返回一个指向树中最大元素的引用
     * @param element
     */
    public T findMax();

}

LinkedBinarySearchTree

package ds.java.ch11;

import ds.java.ch06.listImpl.ElementNotFoundException;
import ds.java.ch11.exceptions.EmptyCollectionException;
import ds.java.ch11.exceptions.NonComparableElementException;

/**
 * @author LbZhang
 * @version 创建时间:2015年11月24日 下午2:10:17
 * @description 类说明
 */
public class LinkedBinarySearchTree<T> extends LinkedBinaryTree<T> implements
        BinarySearchTreeADT<T> {

    /**
     * Creates an empty binary search tree.
     */
    public LinkedBinarySearchTree() {
        super();
    }

    /**
     * Creates a binary search with the specified element as its root.
     * 
     * @param element
     *            the element that will be the root of the new binary search
     *            tree
     */
    public LinkedBinarySearchTree(T element) {
        super(element);

        if (!(element instanceof Comparable))
            throw new NonComparableElementException("LinkedBinarySearchTree");
    }

    /**
     * addElement根据方法给定的元素的值,在树中的恰当的位置添加该元素。如果这个元素不是Comparable,
     * 则addElement方法会抛出一个NonComparableElementException("LinkedBinarySearchTree")
     * 异常。如果树为空,那么新元素就会称为根结点,如果不为空,如果小于则 在左边递归;大于等于,则在右边递归。 元素添加算法的实现:
     * 
     * 
     */
    @Override
    public void addElement(T element) {
        if (!(element instanceof Comparable)) {
            throw new NonComparableElementException("LinkedBinarySearchTree");
        }

        Comparable<T> comElem = (Comparable<T>) element;
        if (isEmpty()) {
            root = new BinaryTreeNode<T>(element);
        } else {
            if (comElem.compareTo(root.getElement()) < 0) {
                if (root.getLeft() == null) {
                    this.getRootNode().setLeft(new BinaryTreeNode<T>(element));
                } else {
                    addElement(element, root.getLeft());
                }
            } else {
                if (root.getRight() == null) {
                    this.getRootNode().setRight(new BinaryTreeNode<T>(element));
                } else {
                    addElement(element, root.getRight());
                }
            }
        }

        modCount++;
    }

    /**
     * 将特定的元素添加到二叉查找树的合适位置
     * 
     * @param element
     * @param left
     */
    private void addElement(T element, BinaryTreeNode<T> node) {
        Comparable<T> comparableElement = (Comparable<T>) element;

        if (comparableElement.compareTo(node.getElement()) < 0) {
            if (node.getLeft() == null)
                node.setLeft(new BinaryTreeNode<T>(element));
            else
                addElement(element, node.getLeft());
        } else {
            if (node.getRight() == null)
                node.setRight(new BinaryTreeNode<T>(element));
            else
                addElement(element, node.getRight());
        }

    }

    /**
     * 负责从二叉查找树中删除给定的comparable元素;或者当在树中找不到给定的目标元素时,则抛出ElementNotFoundException
     * 异常。与前面的线性结构研究不同,这里不能通过简单的通过删除指定结点的相关引用指针而删除该结点。相反这里必须推选出一个结点来取代
     * 要被删除的结点。受保护方法,replacement返回指向一个结点的应用,该结点将代替要删除的结点,选择替换结点有三种情况:
     * 如果被删除结点没有孩子那么repalcement返回null 如果有一个,那么replacement返回这个孩子
     * 如果有两个孩子,则replacement会返回终须后继者。因为相等元素会放在后边
     */
    @Override
    public T removeElement(T targetElement) {

        T result = null;
        if (isEmpty()) {
            throw new ElementNotFoundException("LinkedbinarySearchTree");
        } else {
            BinaryTreeNode<T> parent = null;
            if (((Comparable<T>) targetElement).equals(root.getElement())) {
                result = root.element;
                BinaryTreeNode<T> temp = replacement(root);

                if (temp == null) {
                    root = null;
                } else {

                    root.element = temp.element;
                    root.setLeft(temp.getLeft());
                    root.setRight(temp.getRight());

                }
                modCount--;

            } else {
                parent = root;
                if (((Comparable<T>) targetElement)
                        .compareTo(root.getElement()) < 0) {
                    result = removeElement(targetElement, root.getLeft(),
                            parent);
                } else {
                    result = removeElement(targetElement, root.getRight(),
                            parent);
                }
            }

        }

        return result;
    }

    private T removeElement(T targetElement, BinaryTreeNode<T> node,
            BinaryTreeNode<T> parent) {
        T result = null;

        if (node == null) {
            throw new ElementNotFoundException("LinkedbinarySearchTree");
        } else {

            if (((Comparable<T>) targetElement).equals(node.getElement())) {
                result = node.element;
                BinaryTreeNode<T> temp = replacement(node);

                // 看当前应该删除的降低ian
                if (parent.right == node) {
                    parent.right = temp;
                } else {
                    parent.left = temp;
                }

                modCount--;

            } else {
                parent = node;
                if (((Comparable<T>) targetElement)
                        .compareTo(root.getElement()) < 0) {
                    result = removeElement(targetElement, root.getLeft(),
                            parent);
                } else {
                    result = removeElement(targetElement, root.getRight(),
                            parent);
                }
            }

        }

        return result;
    }

    private BinaryTreeNode<T> replacement(BinaryTreeNode<T> node) {
        BinaryTreeNode<T> result = null;
        if ((node.left == null) && (node.right == null)) {
            result = null;
        } else if ((node.left != null) && (node.right == null)) {
            result = node.left;

        } else if ((node.left == null) && (node.right != null)) {
            result = node.right;
        } else {
            BinaryTreeNode<T> current = node.right;// 初始化右侧第一个结点
            BinaryTreeNode<T> parent = node;

            // 获取右边子树的最左边的结点
            while (current.left != null) {
                parent = current;
                current = current.left;
            }

            current.left = node.left;

            // 如果当前待查询的结点
            if (node.right != current) {
                parent.left = current.right;// 整体的树结构移动就可以了
                current.right = node.right;
            }

            result = current;
        }
        return result;
    }

    /**
     * 负责从二叉查找树中删除制定元素的所有存在;或者,当先在树中找不到指定元素的时候,抛出ElementNotFoundException
     * 异常。如果指定元素不是com类型 则抛出class异常。
     */
    @Override
    public void removeAllOccurrences(T targetElement) {
        removeElement(targetElement);

        try {
            while (contains((T) targetElement))
                removeElement(targetElement);
        }

        catch (Exception ElementNotFoundException) {
        }

    }

    @Override
    public T removeMin() {
        T result = null;

        if (isEmpty())
            throw new EmptyCollectionException("LinkedBinarySearchTree");
        else {
            if (root.left == null) {
                result = root.element;
                root = root.right;
            } else {
                BinaryTreeNode<T> parent = root;
                BinaryTreeNode<T> current = root.left;
                while (current.left != null) {
                    parent = current;
                    current = current.left;
                }
                result = current.element;
                parent.left = current.right;
            }

            modCount--;
        }

        return result;
    }

    @Override
    public T removeMax() {
        T result = null;

        if (isEmpty())
            throw new EmptyCollectionException("LinkedBinarySearchTree");
        else {
            if (root.right == null) {
                result = root.element;
                root = root.left;
            } else {
                BinaryTreeNode<T> parent = root;
                BinaryTreeNode<T> current = root.right;
                while (current.right != null) {
                    parent = current;
                    current = current.right;
                }
                result = current.element;
                parent.right = current.left;
            }

            modCount--;
        }

        return result;
    }

    @Override
    public T findMin() {
        T result = null;

        if (isEmpty())
            throw new EmptyCollectionException("LinkedBinarySearchTree");
        else {
            if (root.left == null) {
                result = root.element;
                //root = root.right;
            } else {
                BinaryTreeNode<T> parent = root;
                BinaryTreeNode<T> current = root.left;
                while (current.left != null) {
                    parent = current;
                    current = current.left;
                }
                result = current.element;
                //parent.left = current.right;
            }

            //modCount--;
        }

        return result;
    }

    @Override
    public T findMax() {
        T result = null;

        if (isEmpty())
            throw new EmptyCollectionException("LinkedBinarySearchTree");
        else {
            if (root.right == null) {
                result = root.element;
                //root = root.left;
            } else {
                BinaryTreeNode<T> parent = root;
                BinaryTreeNode<T> current = root.right;
                while (current.right != null) {
                    parent = current;
                    current = current.right;
                }
                result = current.element;
                //parent.right = current.left;
            }

            //modCount--;
        }

        return result;
    }

}

BinarySearchTreeList
树的主要使用之一是为了为其他集合提供高效实现。

package ds.java.ch11;


import java.util.Iterator;

import ds.java.ch06.listImpl.ListADT;
import ds.java.ch06.listImpl.OrderedListADT;

/**
 * BinarySearchTreeList represents an ordered list implemented using a binary
 * search tree.
 * 
 * @author Lewis and Chase
 * @version 4.0
 */
public class BinarySearchTreeList<T> extends LinkedBinarySearchTree<T>
        implements ListADT<T>, OrderedListADT<T>, Iterable<T> {
    /**
     * Creates an empty BinarySearchTreeList.
     */
    public BinarySearchTreeList() {
        super();
    }

    /**
     * Adds the given element to this list.
     * 
     * @param element
     *            the element to be added to the list
     */
    public void add(T element) {
        addElement(element);
    }

    /**
     * Removes and returns the first element from this list.
     * 
     * @return the first element in the list
     */
    public T removeFirst() {
        return removeMin();
    }

    /**
     * Removes and returns the last element from this list.
     * 
     * @return the last element from the list
     */
    public T removeLast() {
        return removeMax();
    }

    /**
     * Removes and returns the specified element from this list.
     * 
     * @param element
     *            the element being sought in the list
     * @return the element from the list that matches the target
     */
    public T remove(T element) {
        return removeElement(element);
    }

    /**
     * Returns a reference to the first element on this list.
     * 
     * @return a reference to the first element in the list
     */
    public T first() {
        return findMin();
    }

    /**
     * Returns a reference to the last element on this list.
     * 
     * @return a reference to the last element in the list
     */
    public T last() {
        return findMax();
    }

    /**
     * Returns an iterator for the list.
     * 
     * @return an iterator over the elements in the list
     */
    public Iterator<T> iterator() {
        return iteratorInOrder();
    }
}
posted @ 2015-11-24 11:13  snowwolf101  阅读(338)  评论(0编辑  收藏  举报