剑指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 ...
随机推荐
- linux安装jdk(非rpm命令)
首先查看当前linux上安装的jdk版本: java -version 复制build 后面的jdk信息 卸载: rpm -e java-1.6.0_22-fcs 或者 yum -y remove j ...
- Java 之 数据库
1.SQL--结构化查询语言 a.分类:①DDL--数据定义语言 ②DQL--数据查询语言 ③DML--数据操作语言 ④DCL--数据控制语言 b.DDL:包括对数据库的创建.使用.删除,对表的创建. ...
- 自定义RatingBar的一个问题(只显示显示一个星星)
问题一: 在自定义RatingBar时在设置了numStars属性后只显示一张图(一个星星) 解答: 注意准备的替换图片千万不要使用.9PNG格式的图片,要不之后显示一张图(一个星星)! 问题二: 设 ...
- 命名规范(数据库,c#)
Ⅰ. Naming Conventions 1. Table Naming Rule 1a ( Prefix) 新加的Table要加上適當的前缀 e.g. mUsr, eTxn, tmpRolle ...
- Tween Animation----Translate位置移动动画
布局: 在res/下新建一个anim文件夹用来保存动画xml文件 新建一个translate文件 代码: <?xml version="1.0" encoding=" ...
- SQL SERVER 2005修改数据库名称,包括物理文件名和逻辑名称
SQL SERVER 2005修改数据库名称,包括物理文件名和逻辑名称 原来数据库名称为 aa,物理文件名称为 aa.mdf 和 aa_log.ldf: 需要修改数据库名称为 bb,物理文件名 ...
- android studio乱码
http://www.cnblogs.com/Kennytian/p/4449878.html Android Studio中的乱码分好几种,一是IDE的不同窗口里显示乱码,如:logcat筛选框,S ...
- python 时间转换
def getDateTime(time_str): ''' 转换时间 :param time_str: :return: ''' if not isinstance(time_str,unicode ...
- [翻译svg教程]svg学习系列 开篇
目录 [翻译svg教程]svg学习系列 开篇 [翻译svg教程 ]svg 的坐标系统 [翻译svg教程]svg 中的g元素 [翻译svg教程]svg中矩形元素 rect [翻译svg教程]svg中的c ...
- js兼容总结之获取非行间样式
非行间样式案例 #div1 { width: 200px; height: 200px; background: red; } IE获取非行间样式 var oDiv = document.getEle ...