一、題目:二叉樹的鏡像
題目:請完成一個函數,輸入一個二叉樹,該函數輸出它的鏡像。例如下圖所示,左圖是原二叉樹,而右圖則是該二叉樹的鏡像。
該二叉樹節點的定義如下,采用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(); }
3.1 功能測試
// 01.測試完全二叉樹:除了葉子節點,其他節點都有兩個子節點 // 8 // 6 10 // 5 7 9 11 [TestMethod] public void MirrorTest1() { BinaryTreeNode node1 = new BinaryTreeNode(8); BinaryTreeNode node2 = new BinaryTreeNode(6); BinaryTreeNode node3 = new BinaryTreeNode(10); BinaryTreeNode node4 = new BinaryTreeNode(5); BinaryTreeNode node5 = new BinaryTreeNode(7); BinaryTreeNode node6 = new BinaryTreeNode(9); BinaryTreeNode node7 = new BinaryTreeNode(11); SetSubTreeNode(node1, node2, node3); SetSubTreeNode(node2, node4, node5); SetSubTreeNode(node3, node6, node7); BinaryTreeHelper.SetMirrorIteratively(node1); string completed = GetNodeString(node1); Assert.AreEqual(completed,"810611975"); } // 02.測試二叉樹:出葉子結點之外,左右的結點都有且只有一個左子結點 // 8 // 7 // 6 // 5 // 4 [TestMethod] public void MirrorTest2() { BinaryTreeNode node1 = new BinaryTreeNode(8); BinaryTreeNode node2 = new BinaryTreeNode(7); BinaryTreeNode node3 = new BinaryTreeNode(6); BinaryTreeNode node4 = new BinaryTreeNode(5); BinaryTreeNode node5 = new BinaryTreeNode(4); node1.leftChild = node2; node2.leftChild = node3; node3.leftChild = node4; node4.leftChild = node5; BinaryTreeHelper.SetMirrorIteratively(node1); string completed = GetNodeString(node1); Assert.AreEqual(completed, "87654"); } // 03.測試二叉樹:出葉子結點之外,左右的結點都有且只有一個右子結點 // 8 // 7 // 6 // 5 // 4 [TestMethod] public void MirrorTest3() { BinaryTreeNode node1 = new BinaryTreeNode(8); BinaryTreeNode node2 = new BinaryTreeNode(7); BinaryTreeNode node3 = new BinaryTreeNode(6); BinaryTreeNode node4 = new BinaryTreeNode(5); BinaryTreeNode node5 = new BinaryTreeNode(4); node1.rightChild = node2; node2.rightChild = node3; node3.rightChild = node4; node4.rightChild = node5; BinaryTreeHelper.SetMirrorIteratively(node1); string completed = GetNodeString(node1); Assert.AreEqual(completed, "87654"); }
3.2 特殊輸入測試
// 04.測試只有一個結點的二叉樹 // 8 [TestMethod] public void MirrorTest4() { BinaryTreeNode node1 = new BinaryTreeNode(8); BinaryTreeHelper.SetMirrorIteratively(node1); string completed = GetNodeString(node1); Assert.AreEqual(completed, "8"); } // 05.測試空二叉樹:根結點為空指針 [TestMethod] public void MirrorTest5() { BinaryTreeNode node1 = null; BinaryTreeHelper.SetMirrorIteratively(node1); string completed = GetNodeString(node1); Assert.AreEqual(completed, null); }
3.3 測試結果
(1)測試通過情況
(2)代碼覆蓋率