二叉查找树
2012-07-11 15:39
281 查看
原帖地址 http://www.iteye.com/topic/561590
import java.util.Collection; import java.util.Iterator; import java.util.NoSuchElementException; public class BinarySearchTree<E extends Comparable<E>> { public static void main(String[] args) { BinarySearchTree<Integer> bst = new BinarySearchTree<Integer>(); bst.add(50); bst.add(37); bst.add(75); bst.add(25); bst.add(61); bst.add(15); bst.add(30); bst.add(55); bst.add(68); bst.add(28); bst.add(32); bst.add(59); bst.add(36); bst.add(36); //是否包含 System.out.println(bst.contains(36));//true System.out.println(bst.contains(38));//false //大小 System.out.println(bst.size());//13 //遍历 Iterator<Integer> itr = bst.iterator(); while (itr.hasNext()) { //15 25 28 30 32 36 37 50 55 59 61 68 75 System.out.print(itr.next() + " "); } System.out.println(); //删除根叶子节点36 bst.remove(36); System.out.println(bst.size());//12 itr = bst.iterator(); while (itr.hasNext()) { //15 25 28 30 32 37 50 55 59 61 68 75 System.out.print(itr.next() + " "); } System.out.println(); //删除只有一个左子节点的节点37 bst.remove(37); System.out.println(bst.size());//11 itr = bst.iterator(); while (itr.hasNext()) { //15 25 28 30 32 50 55 59 61 68 75 System.out.print(itr.next() + " "); } System.out.println(); //删除只有一个右子节点的节点55 bst.remove(55); System.out.println(bst.size());//10 itr = bst.iterator(); while (itr.hasNext()) { //15 25 28 30 32 50 59 61 68 75 System.out.print(itr.next() + " "); } System.out.println(); //删除有左右子节点的根节点50 bst.remove(50); System.out.println(bst.size());//9 itr = bst.iterator(); while (itr.hasNext()) { //15 25 28 30 32 59 61 68 75 System.out.print(itr.next() + " "); } System.out.println(); //下面通过迭代器删除节点根节点59 itr = bst.iterator(); while (itr.hasNext()) { if (itr.next() == 59) { itr.remove();//删除最近一次next返回的节点 break; } } while (itr.hasNext()) { //61 68 75 System.out.print(itr.next() + " "); itr.remove(); } System.out.println(); System.out.println(bst.size());//5 } private Node root; private int size; public BinarySearchTree() { root = null; } /* * 二叉树插入操作,如果插入节点大于 */ public boolean add(E e) { Node<E> x = root, y = null; int compare = 0; while (x != null) { // y为每次循环x的父节点 y = x; compare = e.compareTo(x.value); /* * 插入节点于当前结点相同则直接返回False * 如果插入节点e如比当前节点x小则将当前节点e指向当前节点的左节点e.left * 否则则将当前节点e指向当前结点右节点e.right */ if (compare == 0) return false; if (compare == 1) x = x.right; else x = x.left; } if (y == null) { // y为空则表示root为空 root = new Node(e, null); } else { // 根据之前判断创建新节点并指定为父节点y的左子节点或右子节点 if (compare == 1) y.right = new Node(e, y); else y.left = new Node(e, y); } size++; return true; } public boolean contains(E e) { return getNode(e) != null; } private Node<E> getNode(E e) { Node<E> node = root; int compare; while (node != null) { compare = e.compareTo(node.value); if (compare == 0) return node; if (compare == 1) node = node.right; else node = node.left; } return null; } public boolean remove(E e) { // 如果为空则直接返回 Node<E> node = getNode(e); if (node == null) return false; removeNode(node); return true; } /* * 如果删除节点n是叶子节点,则直接删除该节点 * 如果删除节点只有一个子节点,则将n的子节点与n的父节点直接连接,然后删除节点n * 如果删除节点n有两个子节点,则使用中序立遍历方式得到直接前置节点c或直接后继节点c得知代替节点n的值,然后删除c */ private void removeNode(Node<E> node) { // 有两个子节点 if (node.left != null && node.right != null) { Node<E> child = intervalNode(node); node.value = child.value; node = child; } // 没有子节点,自身为叶子节点 if (node.left == null && node.right == null) { // if (node.parent == null) { root = null; } else { if (node == node.parent.left) node.parent.left = null; else node.parent.right = null; } } else { // 只有一个节点的情况 Node<E> replace; replace = node.left != null ? node.left : node.right; replace.parent = node.parent; if (node.parent == null) { root = replace; } else if (node == node.parent.left) { node.parent.left = replace; } else { node.parent.right = replace; } } node.parent = null; node.left = node.right = null; size--; } /* * 查找中序遍历的直接后继节点 * * 如果待查找的节点有右子树,则后继节点一定在右子树上,此时右子树上的某个节点可能成为后 * 继节点:一是如果待查节点的右子树没有左子树(有没有右子树无所谓)时,直接就返回该待查节点 * 的右子节点;二是如果待点节点的右子节点有左子树,则查找右子节点的最左边的左子树节点(注, * 该节点一点是左叶子节点或只有一个右子节点的左节点,查找过程要一直向左,即遍历时只向左拐, * 不可向右) * * 如果待查找的节点没有右子树,则需要从该节点向根的方向遍历(不可向左或右拐),后继节点只 * 可能在祖宗节点中产生(包括父节点与根节点在内),此情况分两种:一种就是待查节点为某节点的左 * 子树,则此时的后继为父节点;第二种就是当待查节点为某个节点的右子树时,则需沿根的方向向上找, * 一直找到第一个有左子树的祖宗节点即为后继节点,或到根为止还没有找到(则该节点只可能为中序遍 * 历的最后节点 */ private Node intervalNode(Node node) { if (node == null) { return null; } else if (node.right != null) { /* * 查找50节点的直接后继,查找结果为55 * 50 * \ * 75 * / * 61 * /\ * 55 68 * \ * 59 */ Node<E> child = node.right; while (child.left != null) { child = child.left; } return child; } else { /* * 没有右子树的节点且为父节点的右子节点36的直接后继为37,同样节点68的直接后继为75 * 没有右子树的节点且为父节点的左子节点37的直接后继为50,同样节点28的直接后继为30 * 75为最后节点,所以直接后继为null * * 50 * /\ * 37 75 * / / * 25 61 * /\ /\ * 15 30 55 68 * /\ \ * 28 32 59 * \ * 36 * / * 35 */ Node<E> parent = node.parent; Node<E> current = node; while (parent != null && current == parent.right) { current = parent; parent = parent.parent; } return parent; } } public int size() { return size; } public Iterator<E> iterator() { return new TreeIterator(); } public class TreeIterator implements Iterator<E> { private Node<E> lastReturned; private Node<E> next; private Node<E> endNode; public TreeIterator() { next = root; if (next != null) { while (next.left != null) { next = next.left; } } } public boolean hasPreVious() { return (next != null && intervalNode(next) != null) || endNode != null; } public E previous() { if (next != null && intervalNode(next) == null) { throw new NoSuchElementException(); } if (endNode != null) { lastReturned = next = endNode; endNode = null; } else { lastReturned = next = intervalNode(next); } return lastReturned.value; } public boolean hasNext() { return next != null; } public E next() { if (next == null) throw new NoSuchElementException(); lastReturned = next; next = intervalNode(next); if (next == null) { endNode = lastReturned; } return lastReturned.value; } public void remove() { if (lastReturned == null) { throw new IllegalStateException(); } if (lastReturned.left != null && lastReturned.right != null) { next = lastReturned; } removeNode(lastReturned); lastReturned = null; } } public void preOrder(Collection<E> collect) { preOrder(root, collect); } private final void preOrder(Node<E> n, Collection<E> collect) { if (n != null) { collect.add(n.value); preOrder(n.left, collect); preOrder(n.right, collect); } } public void inOrder(Collection<E> collect) { inOrder(root, collect); } private void inOrder(Node<E> n, Collection<E> collect) { if (n == null) return; inOrder(n.left, collect); collect.add(n.value); inOrder(n.right, collect); } public void postOrder(Collection<E> collect) { postOrder(root, collect); } private final void postOrder(Node<E> n, Collection<E> collect) { if (n == null) return; postOrder(n.left, collect); postOrder(n.right, collect); collect.add(n.value); } private class Node<E> { private E value; private Node parent; private Node left; private Node right; public Node(E value, Node parent) { this.value = value; this.parent = parent; } } }
相关文章推荐
- erl_tree-通用二叉查找树 gb_tree
- [数据结构]二叉查找树 简单实现
- 二叉搜索树(二叉排序树,二叉查找树,二叉检索树)的查找,插入,删除
- 二叉查找树的实现
- 二叉查找树
- 二叉查找树
- C语言实现二叉查找树(BST)的基本操作
- bzoj 1564 [NOI2009]二叉查找树(树形DP)
- 检查一颗二叉树是否是二叉查找树
- 链表——有序链表化为平衡二叉查找树
- lintcode ----在二叉查找树中插入节点
- hdu 5444 继续二叉查找树
- 二叉查找树(一)之 C语言的实现
- 二叉查找树的基本操作实现
- 二叉查找树查找指定排名元素的算法
- 二叉查找树 _ 二叉排序树 _ 二叉搜索树_C++
- 二叉查找树(一)
- BST-二叉查找树
- 数据结构进阶(四)二叉排序树(二叉查找树)
- 每日一省之——使用递归法实现二叉查找树(BST),API齐全