一、问题描述
操作给定的二叉树,将其变换为源二叉树的镜像。
输入描述:
二叉树的镜像定义:源二叉树 8 / \ 6 10 / \ / \ 5 7 9 11 镜像二叉树 8 / \ 10 6 / \ / \ 11 9 7 5
二、算法思想
遍历二叉树,使用递归算法交换节点的左右子树。
三、代码实现
Python实现
class Solution:
# 返回镜像树的根节点
def Mirror(self, root):
# 1.判断节点是否为空
if root != None :
# 2.递归交换左子树
self.Mirror(root.left)
# 3.递归交换右子树
self.Mirror(root.right)
# 4.交换左右孩子节点
root.left, root.right = root.right, root.left
# 节点为空时,递归结束
Java实现
public class Solution {
public void Mirror(TreeNode root) {
TreeNode tmp;
//1.判断节点是否为空
if(root != null){
//2.递归交换左子树
Mirror(root.left);
//3.递归交换右子树
Mirror(root.right);
//4.交换左右孩子节点
tmp = root.left;
root.left = root.right;
root.right = tmp;
}
}
}
四、测试用例
(待测试)
进行功能测试的时候分五种情况:
(1)测试完全二叉树:除了叶子节点,其他节点都有两个子节点
8
/ \
6 10
/ \ / \
5 7 9 11
(2) 测试二叉树:出叶子结点之外,左右的结点都有且只有一个左子结点
8
/
7
/
6
/
5
/
4
(3) 测试二叉树:出叶子结点之外,左右的结点都有且只有一个右子结点
8
\
7
\
6
\
5
\
4
(4) 测试空二叉树:根结点为空指针
(5) 测试只有一个结点的二叉树
参考:
#include<iostream>
#include<stack>
using namespace std;
struct BinaryTreeNode
{
int data;
BinaryTreeNode* leftchild;
BinaryTreeNode* rightchild;
BinaryTreeNode(int t)
{
data = t;
leftchild = NULL;
rightchild = NULL;
}
};
void PreorderTravel(BinaryTreeNode* root)
{
if (root == NULL)
{
return;
}
cout <<root->data << " ";
PreorderTravel(root->leftchild);
PreorderTravel(root->rightchild);
}
//递归实现二叉树的镜像,按照先序遍历,如果遇到空的节点或者叶子节点就返回,否则交换两个子树后再改变左右子树
void MirrorBinaryTree1(BinaryTreeNode* root)
{
if (root == NULL || (root->leftchild == NULL && root->rightchild == NULL))
{
return;
}
BinaryTreeNode * tmp = root->leftchild;
root->leftchild = root->rightchild;
root->rightchild = tmp;
if (root->leftchild)
{
MirrorBinaryTree1(root->leftchild);
}
if (root->rightchild)
{
MirrorBinaryTree1(root->rightchild);
}
}
//循环实现二叉树的镜像,利用栈的“后进先出”特性打印
void MirrorBinaryTree2(BinaryTreeNode* root)
{
if (root == NULL)
{
return;
}
stack<BinaryTreeNode*> stackTreeNode;
stackTreeNode.push(root);
while (stackTreeNode.size() > 0)
{
BinaryTreeNode *parent = stackTreeNode.top();
stackTreeNode.pop();
BinaryTreeNode *Temp = parent->leftchild;
parent->leftchild = parent->rightchild;
parent->rightchild = Temp;
if (parent->leftchild)
{
stackTreeNode.push(parent->leftchild);
}
if (parent->rightchild)
{
stackTreeNode.push(parent->rightchild);
}
}
}
// ====================测试代码====================
// 测试完全二叉树:除了叶子节点,其他节点都有两个子节点
// 8
// 6 10
// 5 7 9 11
BinaryTreeNode* root;
void Test1()
{
root = new BinaryTreeNode(8);
root->leftchild = new BinaryTreeNode(6);
root->rightchild = new BinaryTreeNode(10);
BinaryTreeNode* tmp = root->leftchild;
tmp->leftchild = new BinaryTreeNode(5);
tmp->rightchild = new BinaryTreeNode(7);
tmp = root->rightchild;
tmp->leftchild = new BinaryTreeNode(9);
tmp->rightchild = new BinaryTreeNode(11);
cout << "Test1:测试完全二叉树,除了叶子节点,其他节点都有两个子节点" << endl;
cout << "原二叉树的先序遍历" << endl;
PreorderTravel(root);
cout << endl;
MirrorBinaryTree1(root);
cout << "二叉树镜像后的先序遍历" << endl;
PreorderTravel(root);
cout << endl;
/*MirrorBinaryTree2(root);
cout << "二叉树镜像后的先序遍历" << endl;
PreorderTravel(root);
cout << endl;*/
}
// 测试二叉树:出叶子结点之外,左右的结点都有且只有一个左子结点
// 8
// 7
// 6
// 5
// 4
void Test2()
{
root = new BinaryTreeNode(8);
root->leftchild = new BinaryTreeNode(7);
root->rightchild = NULL;
BinaryTreeNode* tmp = root->leftchild;
tmp->leftchild = new BinaryTreeNode(6);
tmp->rightchild = NULL;
tmp = tmp->leftchild;
tmp->leftchild = new BinaryTreeNode(5);
tmp->rightchild = NULL;
tmp = tmp->leftchild;
tmp->leftchild = new BinaryTreeNode(4);
tmp->rightchild = NULL;
cout << "Test2: 测试二叉树,出叶子结点之外,左右的结点都有且只有一个左子结点" << endl;
cout << "原二叉树的先序遍历" << endl;
PreorderTravel(root);
cout << endl;
MirrorBinaryTree1(root);
cout << "二叉树镜像后的先序遍历" << endl;
PreorderTravel(root);
cout << endl;
/*MirrorBinaryTree2(root);
cout << "二叉树镜像后的先序遍历" << endl;
PreorderTravel(root);
cout << endl;*/
}
// 测试二叉树:出叶子结点之外,左右的结点都有且只有一个右子结点
// 8
// 7
// 6
// 5
// 4
void Test3()
{
root = new BinaryTreeNode(8);
root->leftchild = NULL;
root->rightchild = new BinaryTreeNode(7);
BinaryTreeNode* tmp = root->rightchild;
tmp->leftchild = NULL;
tmp->rightchild = new BinaryTreeNode(6);
tmp = tmp->rightchild;
tmp->leftchild = NULL;
tmp->rightchild = new BinaryTreeNode(5);
tmp = tmp->rightchild;
tmp->leftchild = NULL;
tmp->rightchild = new BinaryTreeNode(4);
cout << "Test3:测试二叉树出叶子结点之外,左右的结点都有且只有一个右子结点" << endl;
cout << "原二叉树的先序遍历" << endl;
PreorderTravel(root);
cout << endl;
MirrorBinaryTree1(root);
cout << "二叉树镜像后的先序遍历" << endl;
PreorderTravel(root);
cout << endl;
/*MirrorBinaryTree2(root);
cout << "二叉树镜像后的先序遍历" << endl;
PreorderTravel(root);
cout << endl;*/
}
// 测试空二叉树:根结点为空指针
void Test4()
{
root = NULL;
cout << "Test4:测试空二叉树,根结点为空指针" << endl;
cout << "原二叉树的先序遍历" << endl;
PreorderTravel(root);
cout << endl;
MirrorBinaryTree1(root);
cout << "二叉树镜像后的先序遍历" << endl;
PreorderTravel(root);
cout << endl;
/*MirrorBinaryTree2(root);
cout << "二叉树镜像后的先序遍历" << endl;
PreorderTravel(root);
cout << endl;*/
}
// 测试只有一个结点的二叉树
void Test5()
{
root = new BinaryTreeNode(8);
root->leftchild = NULL;
root->rightchild = NULL;
cout << "Test5:测试只有一个结点8的二叉树" << endl;
cout << "原二叉树的先序遍历" << endl;
PreorderTravel(root);
cout << endl;
MirrorBinaryTree1(root);
cout << "二叉树镜像后的先序遍历" << endl;
PreorderTravel(root);
cout << endl;
/*MirrorBinaryTree2(root);
cout << "二叉树镜像后的先序遍历" << endl;
PreorderTravel(root);
cout << endl;*/
}
int main()
{
Test1();
Test2();
Test3();
Test4();
Test5();
system("pause");
return 0;
}
五、拓展
1. 后序遍历的思想
public void Mirror(TreeNode root) { TreeNode tmp = null; if (root != null) { Mirror(root.left); // 递归交换左子树 Mirror(root.right); // 递归交换右子树 // 交换左、右孩子结点 tmp = root.left; root.left = root.right; root.right = tmp; } }
2. 先序遍历思想
public void Mirror(TreeNode root) { if (root == null) return; // 叶子结点 if (root.left == null && root.right == null) return; // 交换左右孩子结点 TreeNode pTemp = root.left; root.left = root.right; root.right = pTemp; // 左子树不为空,递归交换左子树 if (root.left != null) Mirror(root.left); // 右子树不为空,递归交换右子树 if (root.right != null) Mirror(root.right); }
3. 层次遍历思想
public void Mirror(TreeNode root) { if (root == null) return; // 初始化一个队列 Queue<TreeNode> queue = new LinkedBlockingQueue<>(); // 根结点入队列 queue.add(root); // 队列不为空 while (!queue.isEmpty()) { TreeNode node = queue.poll(); // 交换该结点的左右孩子结点 if (node.left != null || node.right != null) { TreeNode tmp = node.left; node.left = node.right; node.right = tmp; } // 左子树不为空,则左子树入队列 if (node.left != null) queue.add(node.left); // 右子树不为空,则右子树入队列 if (node.right != null) queue.add(node.right); } }
// 改成用栈也可以。(先根,再右子树,最后左子树)
public void Mirror(TreeNode root) { if (root == null) return; // 初始化一个栈 Stack<TreeNode> s = new Stack<TreeNode>(); // 根结点入栈 s.push(root); // 栈不空 while (!s.empty()) { TreeNode node = s.pop(); if (node.left != null || node.right != null) { TreeNode tmp = node.left; node.left = node.right; node.right = tmp; } if (node.left != null) s.push(node.left); if (node.right != null) s.push(node.right); } }