题目:请完成一个函数,输入一个二叉树,该函数输出它的镜像。例如下图所示,左图是原二叉树,而右图则是该二叉树的镜像。
该二叉树节点的定义如下,采用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 > 0) { 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 > 0) { 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(); }