二叉查找树介绍
二叉查找树作为一种最简单的二叉排序树,它是特殊的二叉树:对于二叉树,假设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