二叉查找树原理分析及查找、插入、删除、遍历实现

二叉查找树介绍

二叉查找树作为一种最简单的二叉排序树,它是特殊的二叉树:对于二叉树,假设x为二叉树中的任意一个结点,x节点包含关键字key,节点x的key值记为key[x]。如果y是x的左子树中的一个结点,则key[y] <= key[x];如果y是x的右子树的一个结点,则key[y]>= key[x]。那么,这棵树就是二叉查找树。

《二叉查找树原理分析及查找、插入、删除、遍历实现》

二叉查找树具有如下性质:

1、如果节点左子树存在,那么左子树中的所有值均小于其根节点的值

2、如果节点右子树存在,那么右子树中所有的值均大于其根节点的值

3、任一节点的左右子树均为二叉搜索树

4、不存在键值相等的两个节点

二叉树结构定义

	//定义二叉查找树节点的结构
	class BSNode<T extends Comparable<T>> {
		BSNode<T> parent;
		BSNode<T> left;
		BSNode<T> right;
		T key;
		BSNode(T key,BSNode<T> parent,BSNode<T> left,BSNode<T> right)
		{
			this.right = right;
			this.left = left;
			this.parent = parent;
			this.key = key;
		}
	}

二叉查找树前序遍历(递归、非递归)

	/**
	 * 采用递归方式对二叉查找树进行先序遍历,
	 * 先遍历根节点,再遍历左子树,最后遍历右子树
	 */
	public void preOrder()
	{
		preOrder(root);
	}
	
	public void preOrder(BSNode<T> node)
	{
		if(node!=null)
		{
			System.out.print(node.key);
			preOrder(node.left);
			preOrder(node.right);
		}
	}

非递归方式

	public void iterPreOrder()
	{
		BSNode<T> node = root;
		Stack<BSNode<T>> stack = new Stack<BSNode<T>>(); //栈用来存放前序遍历回退的路径
		stack.push(null);//作为循环结束的条件
		while(node!=null)
		{
			System.out.println(node.key); //输出节点
			
			if(node.right!=null) //右子女入栈
			{
				stack.push(node.right);
			}
			
			if(node.left!=null){ 
				node = node.left;
			}else{
				node = stack.pop(); //如果没有左子树,则从栈中回退一个节点
			}
		}
	}

二叉查找树中序遍历(递归、非递归)

	/**
	 * 采用递归方式对二叉查找树进行中序遍历
	 * 先遍历左子树,然后遍历根节点,最后遍历右子树
	 */
	public void inOrder()
	{
		inOrder(root);
	}
	
	private void inOrder(BSNode<T> node)
	{
		if(node!=null)
		{
			preOrder(node.left);
			System.out.print(node.key);
			preOrder(node.right);
		}
	}

非递归

	/**
	 * 中序遍历思路
	 *  由于中序遍历先遍历左子树,然后遍历根节点,那么需要一个栈来记录遍历中需要回退的路径,
	 *  
	 */
	public void iterInOrder()
	{
		Stack<BSNode<T>> stack = new Stack<BSNode<T>>(); //栈用来存放前序遍历回退的路径
		BSNode<T> node = root;
		do{
			while(node!=null) //遍历左子树,并将根节点入栈
			{
				stack.push(node);
				node = node.left;
			}
			if(!stack.isEmpty()) //如果栈非空,弹出根节点,输出,获取根节点的右子女
			{
				node = stack.pop();
				System.out.print(node.key);
				node = node.right;
			}
		}while(!stack.isEmpty()||node!=null);//当整个树的根节点的做子女遍历完毕时,栈为空,所以需要根据及诶单判断遍历是否进行
	}

二叉查找树后序遍历(递归、非递归)

	/**
	 * 采用递归方式对二叉查找树进行遍历,
	 * 先遍历左子树,在遍历右子树,最后遍历根节点
	 */
	public void postOrder()
	{
		postOrder(root);
	}
	
	private  void postOrder(BSNode<T> node)
	{
		if(node!=null)
		{
			preOrder(node.left);
			preOrder(node.right);
			System.out.print(node.key);
		}
	}

非递归方式

	//由于 需要记录栈中节点是在左子树还是在右子树,所以对BSNode进行封装,以记录其左右
	class STKNode{
		BSNode<T> node;
		Tag tag;  //采用枚举类型
		STKNode(BSNode<T> node,Tag tag)
		{
			this.tag = tag;
			this.node = node;
		}
	}
enum Tag{
	L,R;
}
	/**
	 * 采用非递归(迭代)的方式对二叉查找树进行后续遍历
	 */
	public void iterPostOrder()
	{
		Stack<STKNode> stack = new Stack<STKNode>();//记录需要回退的路径
		BSNode<T> node = root;
		do{
			STKNode stk = null;
			while(node!=null) //遍历左子树
			{
				stk = new STKNode(node,Tag.L);
				stack.push(stk);
				node = node.left;
			}
			boolean flag = true;
			while(flag&&!stack.isEmpty())
			{
				STKNode stkNode = stack.pop();
				switch(stkNode.tag){
				case L:  //遍历右子树
					stkNode.tag = Tag.R;
					stack.push(stkNode);
					flag = false;
					node = stkNode.node.right; 
					break;
				case R:
					System.out.println(stkNode.node.key);
					break;
				}
			}
		}while(!stack.isEmpty());
	}

二叉查找树层序遍历

	/**
	 * 对二叉查找树进行层序遍历
	 */
	public void levelOrder()
	{
		BSNode<T> node = null;
		Queue<BSNode<T>> queue = new LinkedList<BSNode<T>>(); //用来存放每个节点的子女
		queue.add(root); //将根节点加入队列
		while(!queue.isEmpty())
		{
			node = queue.poll();
			System.out.println(node.key);
			if(node.left!=null) //如果左子女不为空将其接入队列
			{
				queue.add(node.left);
			}
			if(node.right!=null) //如果右子女不为空将其接入队列
			{
				queue.add(node.right);
			}
		}
	}

二叉查找树插入

	/**
	 * 向二叉查找树中插入一个节点
	 * @param key
	 */
	public void insert(T key)
	{
		if(key==null)
			return;
		if(search(key)!=null) //如果关键字已存在,返回
			return;
		BSNode<T> node = new BSNode<T>(key,null,null,null);
		if(root ==null) //如果根节点为空,赋值给根节点
		{
			root = node;
			return;
		}
		
		BSNode<T> temp = node; //临时节点
		BSNode<T> pre = null;
		int com=0;
		while(temp!=null)
		{
			pre = temp;
			com = temp.key.compareTo(key);
			if(com>0)
				temp = temp.left;
			else 
				temp = temp.right;
		}
		
		if(com>0)
		{
			pre.left = node;
		}else{
			pre.right = node;
		}
		node.parent = pre;//指向父节点
	}

二叉查找树查找

	/**
	 *  从二叉查找树中查找一个关键字
	 * @param key
	 * @return
	 */
	public BSNode<T> search(T key)
	{
		if(key==null) //关键字不存在
			return null;
		
		BSNode<T> node = root;
		int com; //记录比较的结果
		while(node!=null)
		{
			com = node.key.compareTo(key);
			if(com>0)
			{
				node = node.left;
			}else if(com<0){
				node = node.right;
			}else{
				return node; //返回
			}
		}
		return null;
	}

二叉查找树删除

	/**
	 * 从二叉查找树中删除一个元素主要分三种情况:
	 * 当节点左右子女均为空时,直接删除该节点
	 * 当节点中只存在一个子女时,将待删除节点的位置直接修改为其子女
	 * 如果节点左右子女均存在时,找到其左子树中最大节点(前驱),或者右子树最小节点(后继)
	 * @param key
	 */
	public void remove(T key)
	{
		if(key==null)
			return;
		BSNode<T> curNode = search(key);//待删除节点
		if(curNode==null) //如果关键字不存在,返回
			return;
		BSNode<T> left,right,parent;
		left = curNode.left;
		right = curNode.right;
		parent = curNode.parent; //被删除节点的
		BSNode<T> replace = null; //最终填充到被删除节点位置
		int com = curNode.key.compareTo(parent.key);//确定该节点是左子女还是右子女
		
		
		if(left==null&&right==null) //左右子女都不存在
		{
			parent = null;
		}
		
		if(left!=null&&right!=null) //左右子女都存在
		{
			BSNode<T> temp = curNode.right,pre = null;
			while(temp!=null) //找到当前节点的左子树中最大节点(前驱)
			{
				pre = temp;
				temp = curNode.right;
			}
			replace = pre;
			if(pre.left!=null) //如果该节点有右子树,则将其右子树移动到该节点位置
			{
				pre.parent.right = pre.left;
				pre.left.parent = pre.parent;
			}
			return;
		}
		
		if(left==null||left==null) //要删除节点只存在一个子女
		{
			BSNode<T> node = null; 
			if(left==null)//找到非空子女
			{
				node = right;
			}else{
				node = left;
			}
			replace = node;
		}
		
		if(com>0)  //修改被解除节点的父亲的子女
		{
			parent.right = replace;
		}else{
			parent.left = replace;
		}
		
		replace.parent = parent;//将该节点父节点指向parent
		replace.left = left;//设置其左右子女
		replace.right = right;
		
	}

二叉查找树销毁

	/**
	 * 销毁 ,采用递归方式销毁左右子树
	 */
	public void destory()
	{
		destory(root);
	}
	
	private void destory(BSNode<T> node)
	{
		if(node!=null)
		{
			if(node.left!=null)
				destory(node.left); //销毁左子树
			if(node.right!=null)
				destory(node.right);//销毁右子树
		}
		node = null;
	}

本文参考如下博文:

http://www.cnblogs.com/skywang12345/p/3576452.html

    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/code4grow/article/details/23201897
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞