求解二叉树镜像

一,问题介绍

求解一棵二叉树的镜像。所谓镜像,就是从二叉树的根到叶结点的每一层,将所有的非叶子结点的孩子进行交换。

比如说,下面两棵二叉树互为镜像:

二,算法分析

 1 /**
 2      * 递归求解二叉树的镜像
 3      * @param root
 4      */
 5     public void mirrorRecursively(BinaryNode<T> root){
 6         //base condition
 7         if(root == null || (root.left == null && root.right == null))
 8             return;
 9
10         //swap nodes
11         BinaryNode<T> tmp;
12         tmp = root.left;
13         root.left = root.right;
14         root.right = tmp;
15
16         //recursively call
17         if(root.left != null)
18             mirrorRecursively(root.left);
19         if(root.right != null)
20             mirrorRecursively(root.right);
21     }

从根结点开始,先交换根结点的左右孩子, 然后再依次交换根结点的左右孩子的孩子......

时间复杂度分析:由于每个结点都会遍历一次,故时间复杂度为O(N),也可以列出递归表达式如下:

递归表达式:T(N)=2T(N/2)+O(1). 由17行到20行的两个if语句,可知将问题规模为N分解成了两个规模为N/2的两个子问题;附加的处理规模为O(1)

解得T(N)=O(N)

尾递归转化为循环:

 1 /**
 2      * 循环实现 求解二叉树的镜像
 3      * @param root
 4      */
 5     public void mirrorLoop(BinaryNode<T> root){
 6         if(root == null || (root.left == null && root.right == null))
 7             return;
 8
 9         swap(root.left, root.right, root);//根的左右孩子的交换
10
11         //处理根的左子树的交换
12         BinaryNode<T> currentNode = root;
13         while(currentNode.left != null)
14         {
15             currentNode = currentNode.left;
16             swap(currentNode.left, currentNode.right, currentNode);
17         }
18
19         //处理根的右子树的交换
20         currentNode = root;
21         while(currentNode.right != null)
22         {
23             currentNode = currentNode.right;
24             swap(currentNode.left, currentNode.right, currentNode);
25         }
26     }

三,完整代码实现

递归实现和非递归实现。由于该递归是一个尾递归,故非递归实现也很简单。

  1 public class BinaryTree_Mirror<T extends Comparable<? super T>> {
  2
  3     private static class BinaryNode<T>{
  4         T element;
  5         BinaryNode<T> left;
  6         BinaryNode<T> right;
  7
  8         public BinaryNode(T element) {
  9             this.element = element;
 10             left = right = null;
 11         }
 12
 13         @Override
 14         public String toString() {
 15             return element.toString();
 16         }
 17     }
 18
 19     private BinaryNode<T> root;
 20
 21     /**
 22      * 向二叉树中插入一个元素
 23      * @param element
 24      */
 25     public void insert(T element){
 26         root = insert(root, element);
 27     }
 28     private BinaryNode<T> insert(BinaryNode<T> root, T element){
 29         if(root == null)
 30             return new BinaryNode<T>(element);
 31         int r = (int)(2*Math.random());
 32         //随机地将元素插入到左子树 或者 右子树中
 33         if(r==0)
 34             root.left = insert(root.left, element);
 35         else
 36             root.right = insert(root.right, element);
 37         return root;
 38     }
 39
 40     public void inOrder(BinaryNode<T> root){
 41         //base condition
 42         if(root == null)
 43             return;
 44
 45         inOrder(root.left);
 46         System.out.print(root + " ");//visit node
 47         inOrder(root.right);
 48     }
 49
 50
 51     /**
 52      * 递归求解二叉树的镜像
 53      * @param root
 54      */
 55     public void mirrorRecursively(BinaryNode<T> root){
 56         //base condition
 57         if(root == null || (root.left == null && root.right == null))
 58             return;
 59
 60         //swap nodes
 61         BinaryNode<T> tmp;
 62         tmp = root.left;
 63         root.left = root.right;
 64         root.right = tmp;
 65
 66         //recursively call
 67         if(root.left != null)
 68             mirrorRecursively(root.left);
 69         if(root.right != null)
 70             mirrorRecursively(root.right);
 71     }
 72
 73     /**
 74      * 循环实现 求解二叉树的镜像
 75      * @param root
 76      */
 77     public void mirrorLoop(BinaryNode<T> root){
 78         if(root == null || (root.left == null && root.right == null))
 79             return;
 80
 81         swap(root.left, root.right, root);
 82
 83         BinaryNode<T> currentNode = root;
 84         while(currentNode.left != null)
 85         {
 86             currentNode = currentNode.left;
 87             swap(currentNode.left, currentNode.right, currentNode);
 88         }
 89
 90         currentNode = root;
 91         while(currentNode.right != null)
 92         {
 93             currentNode = currentNode.right;
 94             swap(currentNode.left, currentNode.right, currentNode);
 95         }
 96     }
 97
 98     /**
 99      * 交换currentNode的左右孩子结点
100      * @param left
101      * @param right
102      * @param currentNode
103      */
104     private void swap(BinaryNode<T> left, BinaryNode<T> right, BinaryNode<T> currentNode){
105         BinaryNode<T> tmpNode;
106         tmpNode = currentNode.left;
107         currentNode.left = currentNode.right;
108         currentNode.right = tmpNode;
109     }
110
111
112     public static void main(String[] args) {
113         BinaryTree_Mirror<Integer> tree1 = new BinaryTree_Mirror<>();
114         BinaryTree_Mirror<Integer> tree2 = new BinaryTree_Mirror<>();
115
116         int[] ele = C2_2_8.algorithm1(4);
117         for (int i = 0; i < ele.length; i++) {
118             tree1.insert(ele[i]);
119             tree2.insert(ele[i]);
120         }
121
122         tree1.mirrorLoop(tree1.root);
123         tree2.mirrorRecursively(tree2.root);
124
125         tree1.inOrder(tree1.root);
126         System.out.println();
127         tree2.inOrder(tree2.root);
128     }
129 }
时间: 2024-08-09 19:49:21

求解二叉树镜像的相关文章

从&quot;按层次输出二叉树&quot;到&quot;求解二叉树深度&quot;的总结

本文是在学习中的总结,欢迎转载但请注明出处:http://write.blog.csdn.net/postedit/41964669 最近在刷LettCode上的算法题,发现好多题目的解题思路大体是一致的,甚至会出现一解对多题的情形,可能一方面原因是我刷的都是简单题,另一方面原因可能是网站有意来提高我们的信心和联想能力.比如有求解二叉树最大深度和求解二叉树最小深度的题目,也有判断两颗树是否完全一致和判断两个树是否轴对称的题目,还有按层次从树根往下输出每层元素和按层次从下往树根输出每层元素的题目等

递归求解二叉树任意一结点的深度

这个事最后一道大题的第一小题 让写个递归算法求解二叉树任意一结点的深度 首先应该去递归找到这个x结点,找到后然后再递归求解以x为根结点的子树的深度,所以我就很规矩(当然我觉得这样写比较明了)写了两个递归函数 当然首先还是得建立二叉排序树 另外注明:是用vs2010写的,没有在vc++6.0上面测试,如果朋友们发现在vc++上有bug,欢迎指出,供后来者看看 贴下自己的代码 //功能:递归算法,求二叉树中以元素值为x的结点为根的子树的深度 //时间:2014-11-23 #include <ios

求二叉树镜像的递归非递归实现

1.二叉树定义: [cpp] view plain copy print? typedef struct BTreeNodeElement_t_ { void *data; } BTreeNodeElement_t; typedef struct BTreeNode_t_ { BTreeNodeElement_t     *m_pElemt; struct BTreeNode_t_    *m_pLeft; struct BTreeNode_t_    *m_pRight; } BTreeNod

C语言强化(十一)二叉树镜像变化 | 要求:不使用递归

用了这么久的递归,现在不让用递归了,你行么? 通过这道题,你可以学会 如何镜像变化一棵二叉树 什么是递归的本质 如何巧妙地使用辅助栈 题目: 输入一颗二元查找树,将该树转换为它的镜像, 即在转换后的二元查找树中,左子树的结点都大于右子树的结点. 要求: 不使用递归 例如输入: 输出: 将二叉树镜像变化的方法很简单,只要把所有节点的左右节点对调就行了,使用递归可以非常容易的实现. 如下为递归方法实现镜像变化的函数 /** 二叉树镜像变化--递归方法实现 */ void Revertsetree_R

剑指offer (19) 二叉树镜像 对称二叉树

题目: 输入一个二叉树,输出其镜像. BinTreeNode* ReverseTree(BinTreeNode* pRoot) { if (pRoot == NULL) return NULL; BinTreeNode* pLeftReverse = ReverseTree(pRoot->left); BinTreeNode* pRightReverse = ReverseTree(pRoot->right); pRoot->left = pRightReverse; pRoot->

二叉树镜像

题目:请完成一个函数,输入一个二叉树,该函数输出它的镜像. 二叉树结点的定义如下: struct BinaryTreeNode { int m_nValue; BinaryTreeNode* m_pLeft; BinaryTreeNode* m_pRight; }; 1.递归实现 2.循环实现 1 #include<stdio.h> 2 #include<stack> 3 4 struct BinaryTreeNode 5 { 6 int m_nValue; 7 BinaryTre

剑指offer——二叉树镜像

操作给定的二叉树,将其变换为源二叉树的镜像. 输入描述: 二叉树的镜像定义:源二叉树 8 / \ 6 10 / \ / \ 5 7 9 11 镜像二叉树 8 / \ 10 6 / \ / \ 11 9 7 5 代码如下: /** public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; } } */ imp

求解二叉树中两个结点的最低公共父结点

一,问题描述 构建一棵二叉树(不一定是二叉查找树),求出该二叉树中某两个结点的最低公共父结点.借用一张图如下: 结点8 和 结点5 的最低公共父结点为 结点2 二,二叉树的构建 与 求二叉树中第K层结点的个数 文章中的第二点:二叉树构建相同 三,求解最低公共父结点的算法实现 有两种思路,一种是通过中序遍历和后序遍历.由于中序遍历是先左子树中的结点,再访问根,再访问右子树中结点,因此这两个结点的公共父结点一定处于这两个结点之间. 如:中序遍历:8, 4, 9, 2, 5, 1, 6, 3, 7  

求解二叉树中两个节点的最近公共祖先(LCA)

/************************************************************************/ /* 非递归的方法 下面是一个简单的复杂度为 O(n) 的算法,解决LCA问题 1) 找到从根到n1的路径,并存储在一个向量或数组中. 2)找到从根到n2的路径,并存储在一个向量或数组中. 3) 遍历这两条路径,直到遇到一个不同的节点,则前面的那个即为最低公共祖先. */ /*************************************