您的位置:首页 > 其它

二叉查找树

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;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: