数据结构(java语言描述)-- 二叉查找树的链式存储结构的实现

先了解下二叉查找树的基本概念:


二叉排序树(Binary Sort Tree)又称二叉查找树(Binary Search Tree),亦称二叉搜索树。 

它或者是一棵空树;或者是具有下列性质的二叉树: 

(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值; 

(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值; 

(3)左、右子树也分别为二叉排序树;


如下图就是一棵二叉树


下面重点解析下二叉查找树的删除操作

在二叉排序树删去一个结点,分三种情况讨论:
  1. 若当前结点为叶子结点,即left(左子树)和right(右子树)均为空树。由于删去叶子结点不破坏整棵树的结构,则只需修改其双亲结点的指针即可。
  2. 若当前结点只有左子树left或右子树right,此时只要令left或right直接成为其双亲结点的左子树(要删除的结点是左子树)或右子树(要删除的结点是右子树)即可,作此修改也不破坏二叉排序树的特性。如下图:
删除前:


删除后:


  1. 若当前结点的左子树和右子树均不空。在删去当前结点之后,为保持其它元素之间的相对位置不变,则需找到当前结点右子树中最小的结点,并用其数据替换当前结点的数据,然后递归的删除找到的最小的结点。如下图:
删除前:


删除后:



下面给出二叉查找树的二叉链表的实现代码



/**
 * 二叉查找树的链式存储结构的实现
 * @author lenovo
 *
 * @param <T>
 */
public class BinarySearchTree <T extends Comparable<? super T>>{	
	
	private static class BinaryNode<T> {
		
		T element;	//节点数据
		BinaryNode<T> left;	//左子节点
		BinaryNode<T> right;	//右子节点
		
		BinaryNode(T theElement) {
			this(theElement, null, null);
		}

		BinaryNode(T theElement, BinaryNode<T> lt, BinaryNode<T> rt) {
			// TODO Auto-generated constructor stub
			 this.element = theElement;
			 this.left = lt;
			 this.right = rt;
		}
	}
	
	private BinaryNode<T> root;	//唯一的数据域,对根节点的引用
	
	public BinarySearchTree() {
		this.root = null;
	}
	
	public void makeEmpty() {
		this.root = null;
	}
	
	public boolean isEmpty() {
		return root == null;
	}
	
	public boolean contains(T x) {
		return contains(x,root);
	}
	
	public BinaryNode<T> findMin() {
		if (isEmpty()) {
			System.out.println("Empty Tree!");
			System.exit(-1);
		}
		return (BinaryNode<T>) findMin(root).element;
	}
	
	public BinaryNode<T> findMax() {
		if (isEmpty()) {
			System.out.println("Empty Tree!");
			System.exit(-1);
		}
		return (BinaryNode<T>) findMax(root).element;
	}
	
	public void insert(T x) {
		root = insert(x, root);
	}
	
	public void remove(T x) {
		root = remove(x, root);
	}
	
	public void printTree() {
		if (isEmpty()) {
			System.out.println("Empty Tree!");
		}
		else {
			printTree(root);
		}
	}
	/**
	 * 在一棵子树中查找项X
	 * @param x
	 * @param t
	 * @return
	 */
	private boolean contains(T x, BinaryNode<T> t) {
		if (t == null) {
			return false;
		}
		
		int compResult = x.compareTo(t.element);
		if (compResult < 0) {
			return contains(x, t.left);		//递归调用
		}
		else if(compResult > 0) {
			return contains(x, t.right);					
		}
		else {
			return true;		//匹配
		}
	}

	/**
	 * 
	 * @param t
	 * @return 返回树中包含最小元的引用
	 */
	private BinaryNode<T> findMin(BinaryNode<T> t) {
		if (t == null) {
			return null;
		}
		else if (t.left == null) {
			return t;
		}
		return findMin(t.left);				//使用递归逐层遍历左子树
	}
	
	/**
	 * 
	 * @param t
	 * @return 返回树中包含最大元的引用
	 */
	private BinaryNode<T> findMax(BinaryNode<T> t) {
		/*if (t == null ){
			return null;
		}
		else if(t.right == null) {
			return t;			
		}
		return findMax(t.right);*/				//使用递归逐层遍历左子树
		
		//非递归实现
		if (t != null) {
			while (t.right != null) {
				t = t.right;
			}				
		}
		return t;		
	}
	/**
	 * 将项X插入一棵子树
	 * @param x
	 * @param t
	 * @return
	 */
	private BinaryNode<T> insert(T x, BinaryNode<T> t) {
		if (t == null) {
			return null;
		}
		
		int compResult = x.compareTo(t.element);
		if (compResult < 0) {
			t.left = insert(x, t.left);
		}
		else if (compResult > 0) {
			t.right = insert(x, t.right);
		}
		else {
			;							//如果重复,什么也不做
		}
		
		return t;
	}
	
	private BinaryNode<T> remove(T x, BinaryNode<T> t) {
		if (t == null) {
			return null;
		}
		int compResult = x.compareTo(t.element);
		if (compResult < 0) {
			t.left = remove(x, t.left);
		}
		else if (compResult > 0) {
			t.right = 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;
	}
	
	private void printTree(BinaryNode<T> t) {
		if (t != null) {
			printTree(t.left);
			System.out.println(t.element);
			printTree(t.right);
		}		
	}




若有任何问题欢迎提出,互相交流学习(●'◡'●)





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值