二叉排序树(二)
2016-04-08 20:06
183 查看
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()); } }
相关文章推荐
- Linux下的畅聊系统
- c++实验3—多分数段函数求值
- CABasicAnimation做动画
- CentOS7 网卡命名
- xcode7.0真机测试出现“Could not find Developer Disk Image"解决方法
- 资本论 卡尔马克思 恩格斯
- 嵌入式设备使用的web服务器 ——thttpd移植 (非常详细,仔细品味一定会有收获)
- jxl.jar例子
- 获取Documents目录下的文件,将相同后缀的文件放到同一数组中
- 省选——重邮二日游
- hi3516a的uboot自动升级相关问题的解决
- hdoj-1496-Equations
- 未来在哪里
- HDU 1062 Text Reverse 字符串反转
- PostgreSQL异步客户端(并模拟redis 数据结构)
- C基础 北京大公司面试简单总结
- JZOJ 4296【NOIP2015模拟11.2】有趣的有趣的家庭菜园
- 关于筛选法的补充 素数较快筛选法 杭电1431
- UIButton
- ROC和AUC介绍以及如何计算AUC