[原]《面试题精选》12.求二元查找树的镜像

题目:输入一颗二元查找树,将该树转换为它的镜像,即在转换后的二元查找树中,左子树的结点都大于右子树的结点。用递归和循环两种方法完成树的镜像转换。

例如输入:

     8
    /  \
  6      10
 /\       /\
5  7    9   11

输出:

      8
    /  \
  10    6
 /\      /\
11  9  7  5

定义二元查找树的结点为:

struct BSTreeNode // a node in the binary search tree (BST)
{
      int          m_nValue; // value of node
      BSTreeNode  *m_pLeft;  // left child of node
      BSTreeNode  *m_pRight; // right child of node
};


分析:题目中有提示用到递归和循环,首先我们根据题目的题型很容易想到用递归,即递归交换左右孩子,所以很容易想到递归方法,难的就是实现。之后再由递归变循环----这个非常像树的三种遍历(递归与非递归实现)讲到的变换方法,就是利用栈或队列实现。

方法一:递归法

import java.util.* ;
public class BinaryMirror{
	public static void main(String args[]){
		MyBinrryTree tree = new MyBinrryTree() ;
		tree.add(8);
		tree.add(6);
		tree.add(10);
		tree.add(5);
		tree.add(7);
		tree.add(9);
		tree.add(11);
		
		tree.println(tree.root) ; //没镜像前的输出

		tree.println(reversal(tree.root)) ; //镜像后的输出
	}
	public static MyTreeNode reversal(MyTreeNode root){
		MyTreeNode temp = null ;
		temp = root.left ;
		root.left = root.right ;
		root.right = temp ;
		
		if(root.left!=null) reversal(root.left) ;
		if(root.right!=null) reversal(root.right) ;
		
		return root ;
	}
}
class MyTreeNode{
	int key ;
	MyTreeNode left ;
	MyTreeNode right ;
	
	public MyTreeNode(int x){
		key = x ;
	}
}
class MyBinrryTree{
	MyTreeNode root ;
	
	public void add(int value){
		MyTreeNode newNode = new MyTreeNode(value) ;
		if(root==null){
			root = newNode ;
		}else{
			MyTreeNode x = null ;
			MyTreeNode y = root ;
			while(y!=null){
				if(newNode.key<y.key){
					x = y ;
					y = y.left ;
					
				}else{
					x = y ;
					y = y.right ;
				}
			}
			if(newNode.key<x.key){
				x.left = newNode ;
			}else{
				x.right = newNode ;
			}
		}
	}
	//二叉树的层次遍历,层次遍历需要用到队列,我们用LinkedList(实现了Queue接口)来实现
	public void println(MyTreeNode root){
		LinkedList<MyTreeNode> queue = new LinkedList<MyTreeNode>() ; 
		queue.add(root) ;
		MyTreeNode n ;
		while(queue.size()!=0){     //注意能使使用queue!=null因为queue初始化本来就不是null
			n = queue.poll() ;
			System.out.println(n.key) ;
			if(n.left!=null){
				queue.add(n.left) ;
			}
			if(n.right!=null){
				queue.add(n.right) ;
			}
		}
	}
}

总结:用到的知识点有①.二叉查找树的实现 ②.层次遍历的实现 ③.双层递归法  递归不熟悉的可看:彻底理解递归


方法二:循环法(只把实现镜像翻转的函数代码列出来,其他部分一样)

public static MyTreeNode reversal(MyTreeNode root){
	MyTreeNode temp = null ;
	MyTreeNode n = null ;
	
	LinkedList<MyTreeNode> queue = new LinkedList<MyTreeNode>() ;
	queue.add(root) ;
	
	while(queue.size()!=0){
		n = queue.poll() ;
		if(n.left!=null) queue.add(n.left) ;
		if(n.right!=null) queue.add(n.right) ;
		temp = n.left ;
		n.left = n.right ;
		n.right = temp ;
	}
	return root ;
}

总结:其实只要你熟悉树的三种遍历(递归与非递归实现),这个问题就很简单了,就是利用到队列存储来实现循环交换。


最后总结下,这道题又说明了《Thinking In Algorithm》系列有多重要了,其中的

基本上自己掌握了上面两篇博客的话,这种类型的题目肯定没问题的。

作者:SpeedMe 发表于2014-4-16 14:53:53 原文链接
阅读:97 评论:0 查看评论

posted on 2014-04-16 14:54  狼牙灬月  阅读(140)  评论(0编辑  收藏  举报

导航