Java实现二叉排序(查找)树的操作

二叉排序树定义:

1.左子树值小于根

2.根的值小于右子树

3.其左右子树又是一颗二叉排序树

抽象数据类型定义,在Java中即是接口的定义

/*
 * 二叉排序树是二叉树的扩展
 * 对于二叉树一般不涉及到插入和删除树中的元素,而在二叉查找树中有
 * 
 * */
public interface BinarySearchTreeADT<T> extends BinaryTreeADT<T>{

	public void addElement(T element) throws NonComparableElementException;
	public T removeElement(T targetElement) throws ElementNotFoundException;
	public void removeAllOcurrs(T targetElement);
	public T removeMin() throws EmptyCollectionException;
	public T removeMax() throws EmptyCollectionException;
	public T findMin();
	public T findMax();
	
}

在二叉树的实现中有关于BinaryTreeADT<T>的定义

具体实现如下:

package com.search;

import java.util.Iterator;

import com.node.BinaryTreeNode;
import com.node.ElementNotFoundException;
import com.node.LinkedBinaryTree;

public class LinkedBinarySearchTree<T> extends LinkedBinaryTree<T> implements
		BinarySearchTreeADT<T> {

	public LinkedBinarySearchTree() {
		super();
	}

	public LinkedBinarySearchTree(T element)
			throws NonComparableElementException {
		super(element);
		if (!(element instanceof Comparable))
			throw new NonComparableElementException("LinkedBinarySearchTree!!");
	}

	/**
	 * 在二叉排序树的适当位置添加一个元素
	 * 1.若树为空:则新添加的元素作为根
	 * 2.若树不为空:则与根比较
	 * 		若小于,则先判断左子树是否为空,若为空直接将其设置为根的左子树,否则继续与左子树比较
	 * 		若大于,则先判断右子树是否为空,若为空直接将其设置为根的右子树,否则继续与右子树比较
	 */
	@SuppressWarnings("unchecked")
	@Override
	public void addElement(T element) throws NonComparableElementException {
		if (!(element instanceof Comparable))
			throw new NonComparableElementException("LinkedBinarySearchTree");
		Comparable<T> comparableElement = (Comparable<T>) element;
		if (isEmpty())
			root = new BinaryTreeNode<T>(element);
		else {
			if (comparableElement.compareTo(root.getElement()) < 0) {
				if (root.getLeft() == null)
					root.setLeft(new BinaryTreeNode<T>(element));
				else {
					addElement(element, root.getLeft());
				}
			} else {
				if (root.getRight() == null)
					root.setRight(new BinaryTreeNode<T>(element));
				else
					addElement(element, root.getRight());
			}
		}
		modCount++;
	}

	/**
	 * @param element
	 * @param node
	 */
	private void addElement(T element, BinaryTreeNode<T> node) {
		@SuppressWarnings("unchecked")
		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());
		}
	}
	
	/**
	 * 删除二叉排序树中的指定元素
	 * 若删除元素,则必须找到代替的元素,不能破坏二叉排序树的特性
	 * 有三种情况:
	 * 1.若删除的是叶子节点,则replacement方法直接返回null
	 * 2.若删除的节点只有一个孩子节点,则replacement方法直接返回这个孩子的引用
	 * 3.若删除的节点有左后孩子,则replacement方法返回中序遍历的后继节点的引用
	 */
	@SuppressWarnings("unchecked")
	@Override
	public T removeElement(T targetElement) throws ElementNotFoundException {
		T result = null;
		if (isEmpty())
			throw new ElementNotFoundException("delete error");
		else {
			BinaryTreeNode<T> parent = null;
			
			if (((Comparable<T>) targetElement).equals(root.getElement())) {//删除的元素是根
				result = root.getElement();
				BinaryTreeNode<T> temp = replacement(root);
				if (temp == null)
					root = null;
				else {
					root.setElement(temp.getElement());
					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;
	}

	@SuppressWarnings("unchecked")
	private T removeElement(T targetElement, BinaryTreeNode<T> node,
			BinaryTreeNode<T> parent) throws ElementNotFoundException {
		T result = null;
		if (node == null)
			throw new ElementNotFoundException("delete error");
		else {
			if (((Comparable<T>) targetElement).equals(node.getElement())) {
				result = node.getElement();
				BinaryTreeNode<T> temp = replacement(node);
				if (parent.getLeft() == node)
					parent.setLeft(temp);
				else
					parent.setRight(temp);
				modCount--;
			} else {
				parent = node;
				if (((Comparable<T>) targetElement)
						.compareTo(node.getElement()) < 0) {
					removeElement(targetElement, node.getLeft(), parent);
				} else {
					removeElement(targetElement, node.getRight(), parent);
				}
			}
		}
		return result;
	}

	private BinaryTreeNode<T> replacement(BinaryTreeNode<T> node) {
		BinaryTreeNode<T> result = null;
		if ((node.getLeft() == null) && (node.getRight() == null))
			result = null;
		else if ((node.getLeft() != null) && (node.getRight() == null))
			result = node.getLeft();
		else if ((node.getLeft() == null) && (node.getRight() != null))
			result = node.getRight();
		else {
			BinaryTreeNode<T> parent = node;
			BinaryTreeNode<T> current = node.getRight();

			while (current.getLeft() != null) {
				parent = current;
				current = current.getLeft();
			}
			current.setLeft(node.getLeft());

			if (node.getRight() != current) {
				parent.setLeft(current.getRight());
				current.setRight(node.getRight());
			}
			result = current;

		}
		return result;
	}

	@Override
	public void removeAllOcurrs(T targetElement) {

		try {
			removeElement(targetElement);
			while (contains((T) targetElement))
				removeElement(targetElement);
		} catch (ElementNotFoundException e) {
		}

	}

	/**
	 * 删除二叉排序树的最小值
	 * 由二叉排序树的特点可知:最小元素位于左子树上,故分为如下三种情况
	 * 1.当没有左子树时:则最小元素为根,则用右子树替换根
	 * 2.当删除的最小元素为叶子节点时:直接将其父亲节点的左子树置空
	 * 3.当删除的最小为树内节点时:直接将其父节点的左孩子指向其右孩子
	 */
	@Override
	public T removeMin() throws EmptyCollectionException {
		T result = null ;
		if(isEmpty())
			throw new EmptyCollectionException("LinkedBinarySearchTree");
		else{
			if(root.getLeft()==null){
				result = root.getElement();
				root = root.getRight();
			}else{
				BinaryTreeNode<T> parent = root ;
				BinaryTreeNode<T> current = root.getLeft();
				
				while(current.getLeft()!=null){
					parent = current ;
					current = current.getLeft();
				}
				result = current.getElement();
				parent.setLeft(current.getRight());
			} 
			modCount --;
		}
		return result;
	}

	/**
	 * 删除二叉排序(查找)树中的最大元素
	 * 由二叉排序树的特性可知,其最大的元素为于右子树上,分为三种情况
	 * 1.当根只有左子树时:则最大元素为根
	 * 2.删除的最大元素为叶子节点时:直接将其父节点的右子树置空
	 * 3.删除的最大元素为树中节点时:父节点的右子树直接指向当前节点的左子树
	 * @throws EmptyCollectionException 
	 */
	@Override
	public T removeMax() throws EmptyCollectionException {
		T result = null ;
		if(isEmpty())
			throw new EmptyCollectionException("LinkedBinarySearchTree");
		else{
			if(root.getRight()==null){
				result = root.getElement();
				root = root.getLeft();
			}else{
				BinaryTreeNode<T> parent = root ;
				BinaryTreeNode<T> current = root.getRight();
				while(current.getRight()!=null){
					parent = current ;
					current = current.getRight();
				}
				result = current.getElement();
				parent.setRight(current.getLeft());
			}
		}
		return result;
	}

	/**
	 *查找二叉排序树的最小元素,
	 *最小元素位于左子树上,一直寻找左子树 
	 */
	@Override
	public T findMin() {
		T result = null ;
		BinaryTreeNode<T> current = root;
		while(current.getLeft()!=null)
			current = current.getLeft();
		result = current.getElement();
		return result;
	}

	@Override
	public T findMax() {
		T result = null ;
		BinaryTreeNode<T> current = root;
		while(current.getRight()!=null)
			current = current.getRight();
		result = current.getElement();
		return result;
	}

	public static void show(Iterator<Integer> iter) {
		while (iter.hasNext()) {
			System.out.print(iter.next() + " ");
		}
		System.out.println();
	}

	public static void main(String[] args) {
		try {
			LinkedBinarySearchTree<Integer> root = new LinkedBinarySearchTree<Integer>();
			root.addElement(10);
			root.addElement(5);
			root.addElement(15);
			root.addElement(3);
			root.addElement(7);
			root.addElement(13);
			Iterator<Integer> iter = root.iteratorInOrder();
			System.out.println("初始化树为:");
			show(iter);
//			try {
//				System.out.println(root.removeElement(5));
//			} catch (ElementNotFoundException e1) {
//				// TODO Auto-generated catch block
//				e1.printStackTrace();
//			}
//			System.out.println("删除5之后:");
//			Iterator<Integer> iter1 = root.iteratorInOrder();
//			show(iter1);
//			root.addElement(10);
//			Iterator<Integer> iter2 = root.iteratorInOrder();
//			show(iter2);
//		
//			root.removeAllOcurrs(10);
//			Iterator<Integer> iter3 = root.iteratorInOrder();
//			show(iter3);
//			try {
//				System.out.println("删除的最小元素为:"+root.removeMin());
//				Iterator<Integer> iter4 = root.iteratorInOrder();
//				show(iter4);
//			} catch (EmptyCollectionException e) {
//				e.printStackTrace();
//			}
//			
//			try {
//				System.out.println("删除的最小元素为:"+root.removeMax());
//				Iterator<Integer> iter4 = root.iteratorInOrder();
//				show(iter4);
//			} catch (EmptyCollectionException e) {
//				e.printStackTrace();
//			}
			
			System.out.println("查找到的最小元素为:"+ root.findMin());
			System.out.println("查找到的最大元素为:"+ root.findMax());
		} catch (NonComparableElementException e) {
			e.printStackTrace();
		}
	}

}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值