剑指Offer面试题:18.二叉树的镜像
一、题目:二叉树的镜像
题目:请完成一个函数,输入一个二叉树,该函数输出它的镜像。例如下图所示,左图是原二叉树,而右图则是该二叉树的镜像。
该二叉树节点的定义如下,采用C#语言描述:
public class BinaryTreeNode
{
public int Data { get; set; }
public BinaryTreeNode leftChild { get; set; }
public BinaryTreeNode rightChild { get; set; } public BinaryTreeNode(int data)
{
this.Data = data;
} public BinaryTreeNode(int data, BinaryTreeNode left, BinaryTreeNode right)
{
this.Data = data;
this.leftChild = left;
this.rightChild = right;
}
}
二、解题思路
2.1 核心步骤
Step1.先序遍历原二叉树的每个节点,如果遍历到的结点有子结点,就交换它的两个子结点。
Step2.递归遍历每个节点的子节点,同样,如果遍历到的子节点有子节点,就交换它的两个子节点。
当交换完所有非叶子结点的左右子结点之后,就得到了树的镜像。下图展示了求二叉树的镜像的过程:

2.2 代码实现
(1)递归版实现
public static void SetMirrorRecursively(BinaryTreeNode root)
{
if (root == null || (root.leftChild == null && root.rightChild == null))
{
return;
} BinaryTreeNode tempNode = root.leftChild;
root.leftChild = root.rightChild;
root.rightChild = tempNode; if (root.leftChild != null)
{
// 递归调整左子树为镜像
SetMirrorRecursively(root.leftChild);
} if (root.rightChild != null)
{
// 递归调整右子树为镜像
SetMirrorRecursively(root.rightChild);
}
}
(2)循环版实现
public static void SetMirrorIteratively(BinaryTreeNode root)
{
if (root == null)
{
return;
} Stack<BinaryTreeNode> stack = new Stack<BinaryTreeNode>();
stack.Push(root); while (stack.Count > )
{
BinaryTreeNode node = stack.Pop(); BinaryTreeNode temp = node.leftChild;
node.leftChild = node.rightChild;
node.rightChild = temp; if (node.leftChild != null)
{
stack.Push(node.leftChild);
} if (node.rightChild != null)
{
stack.Push(node.rightChild);
}
}
}
三、单元测试
为了便于测试,封装了两个辅助方法,设置孩子节点和生成层次遍历的字符串:
/// <summary>
/// 辅助方法:设置root的lChild与rChild
/// </summary>
public void SetSubTreeNode(BinaryTreeNode root, BinaryTreeNode lChild, BinaryTreeNode rChild)
{
if (root == null)
{
return;
} root.leftChild = lChild;
root.rightChild = rChild;
} /// <summary>
/// 辅助方法:生成二叉树元素的字符串用于对比
/// </summary>
public string GetNodeString(BinaryTreeNode root)
{
if (root == null)
{
return null;
} StringBuilder sbResult = new StringBuilder(); Queue<BinaryTreeNode> queueNodes = new Queue<BinaryTreeNode>();
queueNodes.Enqueue(root);
BinaryTreeNode tempNode = null;
// 利用队列先进先出的特性存储节点并输出
while (queueNodes.Count > )
{
tempNode = queueNodes.Dequeue();
sbResult.Append(tempNode.Data); if (tempNode.leftChild != null)
{
queueNodes.Enqueue(tempNode.leftChild);
} if (tempNode.rightChild != null)
{
queueNodes.Enqueue(tempNode.rightChild);
}
} return sbResult.ToString();
}
3.1 功能测试
// 01.测试完全二叉树:除了叶子节点,其他节点都有两个子节点
// 8
// 6 10
// 5 7 9 11
[TestMethod]
public void MirrorTest1()
{
BinaryTreeNode node1 = new BinaryTreeNode();
BinaryTreeNode node2 = new BinaryTreeNode();
BinaryTreeNode node3 = new BinaryTreeNode();
BinaryTreeNode node4 = new BinaryTreeNode();
BinaryTreeNode node5 = new BinaryTreeNode();
BinaryTreeNode node6 = new BinaryTreeNode();
BinaryTreeNode node7 = new BinaryTreeNode(); SetSubTreeNode(node1, node2, node3);
SetSubTreeNode(node2, node4, node5);
SetSubTreeNode(node3, node6, node7); BinaryTreeHelper.SetMirrorIteratively(node1);
string completed = GetNodeString(node1);
Assert.AreEqual(completed,"");
} // 02.测试二叉树:出叶子结点之外,左右的结点都有且只有一个左子结点
// 8
// 7
// 6
// 5
//
[TestMethod]
public void MirrorTest2()
{
BinaryTreeNode node1 = new BinaryTreeNode();
BinaryTreeNode node2 = new BinaryTreeNode();
BinaryTreeNode node3 = new BinaryTreeNode();
BinaryTreeNode node4 = new BinaryTreeNode();
BinaryTreeNode node5 = new BinaryTreeNode(); node1.leftChild = node2;
node2.leftChild = node3;
node3.leftChild = node4;
node4.leftChild = node5; BinaryTreeHelper.SetMirrorIteratively(node1);
string completed = GetNodeString(node1);
Assert.AreEqual(completed, "");
} // 03.测试二叉树:出叶子结点之外,左右的结点都有且只有一个右子结点
// 8
// 7
// 6
// 5
// 4
[TestMethod]
public void MirrorTest3()
{
BinaryTreeNode node1 = new BinaryTreeNode();
BinaryTreeNode node2 = new BinaryTreeNode();
BinaryTreeNode node3 = new BinaryTreeNode();
BinaryTreeNode node4 = new BinaryTreeNode();
BinaryTreeNode node5 = new BinaryTreeNode(); node1.rightChild = node2;
node2.rightChild = node3;
node3.rightChild = node4;
node4.rightChild = node5; BinaryTreeHelper.SetMirrorIteratively(node1);
string completed = GetNodeString(node1);
Assert.AreEqual(completed, "");
}
3.2 特殊输入测试
// 04.测试只有一个结点的二叉树
//
[TestMethod]
public void MirrorTest4()
{
BinaryTreeNode node1 = new BinaryTreeNode(); BinaryTreeHelper.SetMirrorIteratively(node1);
string completed = GetNodeString(node1);
Assert.AreEqual(completed, "");
} // 05.测试空二叉树:根结点为空指针
[TestMethod]
public void MirrorTest5()
{
BinaryTreeNode node1 = null;
BinaryTreeHelper.SetMirrorIteratively(node1);
string completed = GetNodeString(node1);
Assert.AreEqual(completed, null);
}
3.3 测试结果
(1)测试通过情况

(2)代码覆盖率

剑指Offer面试题:18.二叉树的镜像的更多相关文章
- 剑指Offer:面试题19——二叉树的镜像(java实现)
问题描述: 操作给定的二叉树,将其变换为源二叉树的镜像. 二叉树结点定义为: public class TreeNode { int val = 0; TreeNode left = null; Tr ...
- 剑指offer面试题19 二叉树的镜像
题目描述 操作给定的二叉树,将其变换为源二叉树的镜像. 输入描述 二叉树的镜像定义:源二叉树 8 / \ 6 10 / \ / \ 5 7 9 11 镜像二叉树 8 / \ 10 6 / \ / \ ...
- 剑指Offer - 九度1521 - 二叉树的镜像
剑指Offer - 九度1521 - 二叉树的镜像2013-11-30 23:32 题目描述: 输入一个二叉树,输出其镜像. 输入: 输入可能包含多个测试样例,输入以EOF结束.对于每个测试案例,输入 ...
- 剑指offer——面试题18.1:删除链表中重复的节点
// 面试题18(二):删除链表中重复的结点 // 题目:在一个排序的链表中,如何删除重复的结点?例如,在图3.4(a)中重复 // 结点被删除之后,链表如图3.4(b)所示. #include &l ...
- 剑指offer:对称的二叉树(镜像,递归,非递归DFS栈+BFS队列)
1. 题目描述 /** 请实现一个函数,用来判断一颗二叉树是不是对称的. 注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的 */ 2. 递归 思路: /** 1.只要pRoot.left和 ...
- 剑指offer十八之二叉树的镜像
一.题目 操作给定的二叉树,将其变换为源二叉树的镜像.二叉树的镜像定义: 源二叉树 : 8 / \ 6 10 / \ / \ 5 7 9 11 镜像二叉树: 8 / \ 10 6 / \ ...
- 剑指Offer:面试题25——二叉树中和为某一值的路径(java实现)
问题描述: 输入一棵二叉树和一个整数,打印出二叉树中结点指的和为输入整数的所有路径.从树的根结点开始往下一直到叶结点所经过的结点形成一条路径.二叉树结点的定义如下: public class Tree ...
- 剑指Offer:面试题18——树的子结构(java实现)
问题描述: 输入两棵二叉树A和B,判断B是不是A的子结构.二叉树结点的定义如下: public class TreeNode { int val = 0; TreeNode left = null; ...
- [刷题] 剑指offer 面试题18:删除链表节点
要求 给定单向链表的头指针和一个节点指针,在O(1)时间内删除该节点 常规思路:从头节点a开始顺序遍历,发现p指向要删除的节点i,然后把p的m_pNext指向i的下一个节点j,时间复杂度O(n) O( ...
- 剑指offer——面试题18:删除链表的节点
#include"List.h" void DeleteNode(ListNode** pHead,ListNode* pToBeDeleted) { if(*pHead==nul ...
随机推荐
- 卸载oracle 11g grid软件
一,使用deinstall 同样,卸载grid软件在11g中也推出了了卸载工具deinstall卸载同卸载oracle数据库软件 具体可参考:Behaviour of the Oracle De-in ...
- 二.TimesTen原理及应用场景
声明:本文章转自麻袋爸爸 一,TimesTen应用场景 在谈论TimesTen内存数据库应用场景之前,我们先来介绍一下什么是内存数据库,及其工作原理吧.内存数据库,顾名思义就是将数据存放在内存中,并通 ...
- Conditional project or library reference in Visual Studio
Conditional project or library reference in Visual Studio In case you were wondering why you haven’t ...
- Puppet自动化运维-C/S架构概念(1)
1.Puppet工作模式 (1)采用C/S架构(即是server<=>client) (2)Master 会对自己形成自签名CA中心,对Agent端进行证书颁发,验证通过才允许Agent( ...
- ASP.NET - 回滚事务
SqlConnection con =new SqlConnection(ConnectionDb.conStr);//获取数据库连接 con.Open();//打开连接 SqlTransaction ...
- mac linux 删除一个文件下边所有文件和文件夹
sudo rm -r -f 目录
- screen
https://www.ibm.com/developerworks/cn/linux/l-cn-screen/ http://www.cnblogs.com/mchina/archive/2013/ ...
- mysql_connect() php7不支持,php5.5可以,是废弃函数
天用了PHP7,发现和PHP5变化还挺大的,最大的就是MySQL的连接库变了. PHP5中使用mysql_connect()函数进行连接,但实际上,PHP5.5开始,MySQL就不推荐使用了,属于废弃 ...
- haha3
YOU - fhasd - fdks jf > jd sfkjd sf </div><div><span >print "helloworld&qu ...
- HDU 3584 Cube (三维 树状数组)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3584 Cube Problem Description Given an N*N*N cube A, ...
