神奇的二叉查找树,停不下来的思维风暴,来这里,我将告诉你它的实现原理


二叉查找树是树ADT的一种,它的性质是对于树中的每个节点X,它的左子树中所有项的值均小于X的值,而X的右子树中所有项的值均大于X的值。

*ADT:抽象数据类型:带有一组操作的一些对象的集合。


一个简单的二叉查找树如图所示:


二叉查找树要求所有的项能够排序,我们需要提供一个interface来表示这个性质,这个接口就是Comparable,实现这个接口,树中的两项总可以使用compareTo方法进行比较。


在二叉查找树的实现类BinarySearchTree中只有一个唯一的数据域,这个数据域表示对根节点的引用,在空树中,这个引用是Null。


节点是用BinaryNode这个内部泛型类来实现,包含三个数据域,一个是当前节点值,一个是对左儿子的引用,一个是对右儿子的引用。


包含以下方法的实现:

1、contains(AnyType x, BinaryNode<AnyType> t)                  

  如果树中存在含有项X的节点,那么这个方法返回true,如果树中不包含这个节点,则返回false


2、findMIn和findMax

  findMin,从根开始并且只要有左儿子就向左遍历,终止点就是最小元素。findMax,从根节点开始并且只要有右儿子就向右遍历,终止点就是最大元素。


3、insert

  从根节点开始遍历,如果遍历到插入值X,则什么也不做,否则将X插入到遍历路径上的最后一个节点上。


4、remove

  如果节点是一片树叶,则立即删除。如果节点有一个儿子,则将当前节点设为其左/右儿子节点。如果节点有两个儿子,用其右子树中最小的节点替代该节点,并将这个最小节点删除。


5、printTree

  打印该树

 

实现代码如下:

   

/**
 * @description   
 * @author Zhangx
 * @date 2015年12月3日 下午7:36:08
 * @version 1.0 
 */
public class BinarySearchTree<AnyType extends Comparable<? super AnyType>>{
	
	private BinaryNode<AnyType> root;  //对二叉查找树根节点的引用
	
	/**
	 * 初始化,默认为空树
	 */
	public BinarySearchTree(){        
		root = null;
	}
	 
	/**
	 * 清空当前的二叉查找树
	 */
	public void makeEmpty(){           
		root = null;
	}
	
	/**
	 * 该树是否为空树
	 * @return boolean
	 */
	public boolean isEmpty(){
		return root == null;
	}
	
	/**
	 * 查找树中是否有元素X
	 * @param x
	 * @return boolean
	 */
	public boolean contains(AnyType x){
		return contains(x, root);
	}
	
	/**
	 * 查找最小值,如果是空树则抛出异常
	 * @return boolean
	 */
	public AnyType findMin(){
		if(isEmpty())
			throw new UnderflowException();
		
		return findMin(root).element;
	}
	
	/**
	 * 查找最大值,如果是空树则抛出异常
	 * @return boolean
	 */
	public AnyType findMax(){
		if(isEmpty())
			throw new UnderflowException();
		
		return findMax(root).element;
	}
	
	/**
	 * 插入元素X
	 * @param x
	 */
	public void insert(AnyType x){
		root = insert(x, root);
	}
	
	/**
	 * 在树中删除元素X
	 * @param x
	 */
	public void remove(AnyType x){
		root = remove(x, root);
	}
	
	/**
	 * 打印树的所有元素,如果是空树则打印"is a empty tree"
	 */
	public void printTree(){
		if(isEmpty()){
			System.out.println("is a empty tree");
		}else{
			printTree(root);
		}
	}
	
	/**
	 * 在树t中查找元素x
	 * @param x
	 * @param t
	 * @return boolean
	 */
	private boolean contains(AnyType x, BinaryNode<AnyType> t){
		
		if(t == null){
			return false;
		}
		
		int compareResult = x.compareTo(t.element);
		
		if(compareResult<0){                        //x如果比节点值小,继续查找左子树
			return contains(x, t.left);         
		}else if(compareResult>0){                  //x如果比节点值大,继续查找右子树
			return contains(x, t.right);
		}else{
			return true;
		}
	}
	
	/**
	 * 在树t中查找最小值
	 * @param t
	 * @return BinaryNode<AnyType>
	 */
	private BinaryNode<AnyType> findMin(BinaryNode<AnyType> t){
		
		if(t == null){
			return null;
		}
		
		if(t.left == null){           //不断遍历左子树,直到找到最小值,即没有左儿子的节点
			return t;
		}else{
			return findMin(t.left);        
		}
	}
	
	/**
	 * 在树t中查找最大值
	 * @param t
	 * @return BinaryNode<AnyType>
	 */
	private BinaryNode<AnyType> findMax(BinaryNode<AnyType> t){
		
		if(t == null){
			return null;
		}
		
		if(t.right == null){         //不断遍历右子树,直到找到最大值,即没有右儿子的节点
			return t;
		}else{
			return findMax(t.right);
		}
		
	}
	
	/**
	 * 将元素x插入树t
	 * @param x
	 * @param t
	 * @return BinaryNode<AnyType>
	 */
	private BinaryNode<AnyType> insert(AnyType x, BinaryNode<AnyType> t){
		
		if(t == null){
			return new BinaryNode(x);        //如果当前节点为空,则将新节点插入
		}
		
		int compareResult = x.compareTo(t.element);
		
		if(compareResult<0){
			return insert(x, t.left);
		}else if(compareResult>0){
			return insert(x, t.right);
		}else{
			return t;
		}
	}
	
	/**
	 * 在树t中删除元素x
	 * @param x
	 * @param t
	 * @return BinaryNode<AnyType>
	 */
	private BinaryNode<AnyType> remove(AnyType x, BinaryNode<AnyType> t){
		
		if(t == null){                    //没有找到节点x
			return t;
		}
		
		int compareResult = x.compareTo(t.element);
		
		if(compareResult<0){
			t = remove(x, t.left);
		}else if(compareResult>0){
			t = remove(x, t.right);
		}else if(t.left!=null&&t.right!=null){         //找到节点且节点有两个儿子
			t.element = findMin(t.right).element;
			t.right = remove(t.element, t.right);
		}else{                                         //找到节点且节点为树叶或只有一个儿子
			t = (t.left != null)?t.left:t.right;
		}
		return t;
	}
	
	/**
	 * 打印树,顺序为先打印左儿子再打印根节点最后打印右儿子,从叶子节点开始打印
	 * @param t
	 */
	private void printTree(BinaryNode<AnyType> t){
		
		if(t != null){
			printTree(t.left);
			System.out.println(t.element);
			printTree(t.right);
		}
	}
	
	/**
	 * 树的每一个节点元素,包含三个数据域,一个是当前节点值,一个是对左儿子的引用,一个是对右儿子的引用。
	 * @author Zhangxin
	 *
	 * @param <AnyType>
	 */
	private static class BinaryNode<AnyType>{
		
		/**
		 * 初始节点,只设置节点值
		 * @param element
		 */
		public BinaryNode(AnyType element){
			this(element, null, null);
		}
		
		/**
		 * 初始节点,包含节点值,左儿子引用,右儿子引用
		 * @param element
		 * @param left
		 * @param right
		 */
		public BinaryNode(AnyType element, BinaryNode<AnyType> left, BinaryNode<AnyType> right){
			this.element = element;
			this.left = left;
			this.right = right;
		}
		
		AnyType element;                    //节点值
		BinaryNode<AnyType> left;           //左儿子引用
		BinaryNode<AnyType> right;          //右儿子引用
	}
	
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值