题目:
请完成一个函数,输入一颗二叉树,该函数输出它的镜像。
分析:
先前序遍历这棵树的每个节点,如果遍历到的节点有子节点,就交换它的两个子节点。
当交换完的所有非叶节点的左右子节点之后,就得到树的镜像
有三种方法解决该问题
1,递归,
2,前序非递归,
3,层序非递归,
首先声明二叉树,
递归方法,根节点不为空,交换左子树和右子树,递归将子树的节点也进行交换。
前序非递归,前序遍历的非递归 根左右,
只要某节点有左子节点,就不断压入栈中,直到没有左子节点时弹出,
接着将根节点指向右子树,重复上述过程,
层序非递归,层序遍历广度优先搜索,需要用到队列,现将根节点入列,然后弹出根节点将根节点的子节点入列,不断重复,直到队列为空
将同一层的节点都进行交换
首先将根节点放入队列中,队列不为空,拿出一个节点//非叶子节点的前提下,交换左右子节点,当左子节点不为空时,将左子节点放入队列,右子节点同理。
package com.helan.d;
import sun.reflect.generics.tree.Tree;
import java.util.LinkedList;
public class MirrorOfBinaryTree {
public static class TreeNode{
int val;
TreeNode rightTree;
TreeNode leftTree;
public TreeNode(int val) {
this.val = val;
}
public TreeNode(){}
}
public static void mirrorRec(TreeNode root){
if(root==null){
return ;
}
TreeNode tem=root.leftTree;
root.leftTree=root.rightTree;
root.rightTree=tem;
mirrorRec(root.leftTree);
mirrorRec(root.rightTree);
}
//创建二叉树结点
public static TreeNode createBinaryTreeNode(int val){
TreeNode root=new TreeNode();
root.val=val;
root.rightTree=null;
root.leftTree=null;
return root;
}
//连接二叉树结点
public static void connectTreeNodes(TreeNode pParents, TreeNode pLeft,TreeNode pRight){
if(pParents!=null){
pParents.leftTree=pLeft;
pParents.rightTree=pRight;
}
}
public static void printTreeNode(TreeNode treeNode){
if(treeNode!=null){
System.out.println("节点的值为:"+treeNode.val);
if (treeNode.leftTree!=null){
System.out.println("节点左子的值为:"+treeNode.leftTree.val);
}else {
System.out.println("节点左子为空!");
}
if (treeNode.rightTree!=null){
System.out.println("节点右子的值为:"+treeNode.rightTree.val);
}else {
System.out.println("节点右子为空!");
}
}
}
private void mirrorIterPre(TreeNode root) {
//前序非递归
LinkedList<TreeNode> stack=new LinkedList<>();
while (root!=null||!stack.isEmpty()){
while(root!=null){
stack.push(root);
if(root.rightTree!=null||root.leftTree!=null){
TreeNode tem=root.leftTree;
root.leftTree=root.rightTree;
root.rightTree=tem;
}
root=root.leftTree;
}
if(!stack.isEmpty()){
root=stack.pop();
root=root.rightTree;
}
}
}
private void mirrorIterLevel(TreeNode root) {
if(root==null){
return;
}
LinkedList<TreeNode> queue=new LinkedList<>();
queue.offer(root);//先进先出
while(!queue.isEmpty()){
TreeNode node=queue.poll();
if(node.rightTree!=null||node.leftTree!=null){
TreeNode tem=node.leftTree;
node.leftTree=node.rightTree;
node.rightTree=tem;
}
if(node.leftTree!=null){
queue.offer(node.leftTree);
}
if(node.rightTree!=null){
queue.offer(node.rightTree);
}
}
}
public static void printTree(TreeNode pRoot){
printTreeNode(pRoot);
if(pRoot!=null){
if(pRoot.leftTree!=null){
printTree(pRoot.leftTree);
}
if(pRoot.rightTree!=null){
printTree(pRoot.rightTree);
}
}
}
// ====================测试代码====================
// 测试完全二叉树:除了叶子节点,其他节点都有两个子节点
// 8
// 6 10
// 5 7 9 11
void test1(){
TreeNode pNode8 = createBinaryTreeNode(8);
TreeNode pNode6 = createBinaryTreeNode(6);
TreeNode pNode10 = createBinaryTreeNode(10);
TreeNode pNode5 = createBinaryTreeNode(5);
TreeNode pNode7 = createBinaryTreeNode(7);
TreeNode pNode9 = createBinaryTreeNode(9);
TreeNode pNode11 = createBinaryTreeNode(11);
connectTreeNodes(pNode8, pNode6, pNode10);
connectTreeNodes(pNode6, pNode5, pNode7);
connectTreeNodes(pNode10, pNode9, pNode11);
printTree(pNode8);//打印原始树
// System.out.print("=====Test1: 递归镜像=====\n");
// mirrorRec(pNode8);
// printTree(pNode8);//打印镜像树
//
// System.out.print("=====Test1: 前序镜像=====\n");
// mirrorIterPre(pNode8);
// printTree(pNode8);
System.out.print("=====Test1: 层序镜像=====\n");
mirrorIterLevel(pNode8);
printTree(pNode8);
}
// 测试二叉树:出叶子结点之外,左右的结点都有且只有一个左子结点
// 8
// 7
// 6
// 5
// 4
public void test2(){
System.out.print("=====Test2 starts:=====\n");
TreeNode pNode8 = createBinaryTreeNode(8);
TreeNode pNode7 = createBinaryTreeNode(7);
TreeNode pNode6 = createBinaryTreeNode(6);
TreeNode pNode5 = createBinaryTreeNode(5);
TreeNode pNode4 = createBinaryTreeNode(4);
connectTreeNodes(pNode8, pNode7, null);
connectTreeNodes(pNode7, pNode6, null);
connectTreeNodes(pNode6, pNode5, null);
connectTreeNodes(pNode5, pNode4, null);
printTree(pNode8);
// System.out.print("=====Test2: 递归镜像=====\n");
// mirrorRec(pNode8);
// printTree(pNode8);
// System.out.println("前序遍历的镜像");
// mirrorIterPre(pNode8);
// printTree(pNode8);//打印镜像树
System.out.print("=====Test1: 层序镜像=====\n");
mirrorIterLevel(pNode8);
printTree(pNode8);
}
// 测试二叉树:出叶子结点之外,左右的结点都有且只有一个右子结点
// 8
// 7
// 6
// 5
// 4
public void test3(){
System.out.print("=====Test3 starts:=====\n");
TreeNode pNode8 = createBinaryTreeNode(8);
TreeNode pNode7 = createBinaryTreeNode(7);
TreeNode pNode6 = createBinaryTreeNode(6);
TreeNode pNode5 = createBinaryTreeNode(5);
TreeNode pNode4 = createBinaryTreeNode(4);
connectTreeNodes(pNode8, null, pNode7);
connectTreeNodes(pNode7, null, pNode6);
connectTreeNodes(pNode6, null, pNode5);
connectTreeNodes(pNode5, null, pNode4);
printTree(pNode8);
// System.out.print("=====Test3: 递归镜像=====\n");
// mirrorRec(pNode8);
// printTree(pNode8);
// System.out.println("前序遍历的镜像");
// mirrorIterPre(pNode8);
// printTree(pNode8);//打印镜像树
System.out.print("=====Test3: 层序镜像=====\n");
mirrorIterLevel(pNode8);
printTree(pNode8);
}
// 测试空二叉树:根结点为空指针
public void test4(){
System.out.print("=====Test4 starts:=====\n");
TreeNode pNode = null;
printTree(pNode);
// System.out.print("=====Test4: 递归镜像=====\n");
// mirrorRec(pNode);
// printTree(pNode);
// System.out.println("前序遍历的镜像");
// mirrorIterPre(pNode);
// printTree(pNode);//打印镜像树
System.out.print("=====Test1: 层序镜像=====\n");
mirrorIterLevel(pNode);
printTree(pNode);
}
// 测试只有一个结点的二叉树
public void test5(){
System.out.print("=====Test5 starts:=====\n");
TreeNode pNode8 = createBinaryTreeNode(8);
printTree(pNode8);
// System.out.print("=====Test5: 递归镜像=====\n");
// mirrorRec(pNode8);
// printTree(pNode8);
// System.out.print("=====Test5: 前序镜像=====\n");
// System.out.println("前序遍历的镜像");
// mirrorIterPre(pNode8);
// printTree(pNode8);//打
System.out.print("=====Test1: 层序镜像=====\n");
mirrorIterLevel(pNode8);
printTree(pNode8);
}
public static void main(String args[]){
new MirrorOfBinaryTree().test1();
new MirrorOfBinaryTree().test2();
new MirrorOfBinaryTree().test3();
new MirrorOfBinaryTree().test4();
new MirrorOfBinaryTree().test5();
}
}