二叉排序树(二)

package exerciseTest;

import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * 二叉排序树,也可以成为二叉查找树 它的性质如下: 1.若它的左子树不为空,则左子树上所有的节点均小于其根节点
 * 2.若它的右子树不为空,则右子树上所有的节点的值均大于根节点 3.它的左右子树也分别为二叉排序树
 * 
 * 简单起见,假设树中元素都实现了Comparable接口或者他们可以按自然顺序比较
 */
public class BinarySortTree<E> {

    /**
     * 根节点
     */
    private TreeNode<E> root = null;

    /**
     * 树中元素个数
     */
    private int size = 0;

    public BinarySortTree() {

    }

    public int size() {
        return size;
    }

    public E getRoot() {
        return root == null ? null : root.element;
    }

    /**
     * 查找指定元素element是否在树中存在,如果查找失败确认其添加的位置 查找成功直接返回
     * 
     * @param t
     *            表示从此节点开始往下查找
     * @param f
     *            保存t的父节点
     * @param p
     *            若查找成功p指向此数据元素节点,否则返回查找路径上的最后一个节点
     * 
     *            这是递归实现
     */
    private boolean searchBST(TreeNode<E> t, Object element, TreeNode<E> f, TreeNode<E> p) {
        if (t == null) {
            p = f;
            return false;
        }
        Comparable<? super E> e = (Comparable<? super E>) element;
        int cmp = e.compareTo(t.element);
        if (cmp < 0) {
            return searchBST(t.left, element, t, p);
        } else if (cmp > 0) {
            return searchBST(t.right, element, t, p);
        } else {
            p = t;
            return true;
        }
    }

    /**
     * 
     * 这是非递归实现
     */
    private boolean searchBST(Object element, TreeNode[] p) {
        Comparable<? super E> e = (Comparable<? super E>) element;
        TreeNode<E> parent = root;
        TreeNode<E> pp = null;
        // 保存parent父节点
        while (parent != null) {
            int cmp = e.compareTo(parent.element);
            pp = parent;
            if (cmp < 0) {
                parent = parent.left;
            } else if (cmp > 0) {
                parent = parent.right;
            } else {
                p[0] = parent;
                return true;
            }
        }
        p[0] = pp;
        return false;
    }

    /**
     * 首先查找二叉排序树,如果找不到指定元素 则插入到二叉树中
     */
    public boolean add(E element) {
        TreeNode<E> t = root;
        if (t == null) {
            // 如果根节点为空
            root = new TreeNode<E>(element, null);
            size = 1;
            return false;
        }
        Comparable<? super E> e = (Comparable<? super E>) element;
        TreeNode[] p = new TreeNode[1];
        if (!searchBST(element, p)) {
            // 查找失败,插入元素
            TreeNode<E> s = new TreeNode<E>(element, p[0]);
            int cmp = e.compareTo((E) p[0].element);
            if (cmp < 0) {
                p[0].left = s;
            }
            if (cmp > 0) {
                p[0].right = s;
            }
            size++;
            return true;
        }
        return false;
    }

    /**
     * 移除节点,同时调整二叉树使之为二叉排序树 实现原理: 假设要删除的节点为p,其父节点为f,而p是f的左节点 分三种情况讨论:
     * 1.若p为叶子节点,直接删除 2.若p有只有一个左孩子或者一个右孩子,则删除p,使PL或者PR为f的左子树
     * 3.若p的左右子树均不为空,由二叉排序树的特点可知在删除p前,中序遍历此二叉树
     * 可以得到一个有序序列,在删去p后为了保持其他元素的相对位置不变,可以这样做:
     * 令p的直接前驱(或直接后继)替代p,然后删除其直接前驱或直接后继。其直接前驱可由 中序遍历的特点获得
     */
    public boolean remove(Object o) {
        //没有赋值操作
        TreeNode[] p = new TreeNode[1];
        if (searchBST(o, p)) {
            // 查找成功,删除元素
            deleteEntry(p[0]);
            return true;
        }
        return false;
    }

    private void deleteEntry(TreeNode<E> p) {
        size--;
        // 如果p左右子树都不为空,找到其直接后继,替换p
        if (p.left != null && p.right != null) {
            TreeNode<E> s = successor(p);
            p.element = s.element;
            p = s;  //yong s lai tidai p
        }
        TreeNode<E> replacement = (p.left != null ? p.left : p.right);

        if (replacement != null) { // 如果其左右子树有其一不为空
            replacement.parent = p.parent;
            if (p.parent == null) // 如果p为root节点
                root = replacement;
            else if (p == p.parent.left) // 如果p是左孩子
                p.parent.left = replacement;
            else
                // 如果p是右孩子
                p.parent.right = replacement;

            p.left = p.right = p.parent = null; // p的指针清空

        } else if (p.parent == null) { // 如果全树只有一个节点
            root = null;
        } else { // 左右子树都为空,p为叶子节点
            if (p.parent != null) {
                if (p == p.parent.left)
                    p.parent.left = null;
                else if (p == p.parent.right)
                    p.parent.right = null;
                p.parent = null;
            }
        }

    }

    /**
     * 返回以中序遍历方式遍历树时,t的直接后继
     */
    static <E> TreeNode<E> successor(TreeNode<E> t) {
        if (t == null)
            return null;
        else if (t.right != null) {
            // 往右,然后向左直到尽头
            TreeNode<E> p = t.right;
            while (p.left != null)
                p = p.left;
            return p;
        } else { // right为空,如果t是p的左子树,则p为t的直接后继
            TreeNode<E> p = t.parent;
            TreeNode<E> ch = t;
            while (p != null && ch == p.right) {
                // 如果t是p的右子树,则继续向上搜索其直接后继
                ch = p;
                p = p.parent;
            }
            return p;
        }
    }

    public Iterator<E> itrator() {
        return new BinarySortIterator();
    }

    // 返回中序遍历此树的迭代器
    private class BinarySortIterator implements Iterator<E> {
        TreeNode<E> next;
        TreeNode<E> lastReturned;

        public BinarySortIterator() {
            TreeNode<E> s = root;
            if (s != null) {
                while (s.left != null) {
                    // 找到中序遍历的第一个元素
                    s = s.left;
                }
            }
            next = s;
            // 赋给next
        }

        @Override
        public boolean hasNext() {
            return next != null;
        }

        @Override
        public E next() {
            TreeNode<E> e = next;
            if (e == null)
                throw new NoSuchElementException();
            next = successor(e);
            lastReturned = e;
            return e.element;
        }

        @Override
        public void remove() {
            if (lastReturned == null)
                throw new IllegalStateException();
            // deleted entries are replaced by their successors
            if (lastReturned.left != null && lastReturned.right != null)
                next = lastReturned;
            deleteEntry(lastReturned);
            lastReturned = null;
        }
    }

    /**
     * 树节点,为方便起见不写get,Set方法
     */

    static class TreeNode<E> {
        E element;
        TreeNode<E> parent;
        TreeNode<E> left;
        TreeNode<E> right;

        public TreeNode(E element, TreeNode<E> parent) {
            this.element = element;
            this.parent = parent;
        }
        public TreeNode() {
        }
    }

    // just for test
    public static void main(String[] args) {
        BinarySortTree<Integer> tree = new BinarySortTree<Integer>();
        tree.add(45);
        tree.add(24);
        tree.add(53);
        tree.add(45);
        tree.add(12);
        tree.add(90);

        System.out.println(tree.remove(400));
        System.out.println(tree.remove(45));
        System.out.println("root=" + tree.getRoot());
        Iterator<Integer> it = tree.itrator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
        System.out.println(tree.size());
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值