二叉树的镜像

一、问题描述

    操作给定的二叉树,将其变换为源二叉树的镜像。

输入描述:

二叉树的镜像定义:源二叉树 
    	    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. 后序遍历的思想

  1. public void Mirror(TreeNode root)
  2. {
  3. TreeNode tmp = null;
  4. if (root != null)
  5. {
  6. Mirror(root.left); // 递归交换左子树
  7. Mirror(root.right); // 递归交换右子树
  8. // 交换左、右孩子结点
  9. tmp = root.left;
  10. root.left = root.right;
  11. root.right = tmp;
  12. }
  13. }

2. 先序遍历思想

  1. public void Mirror(TreeNode root)
  2. {
  3. if (root == null)
  4. return;
  5. // 叶子结点
  6. if (root.left == null && root.right == null)
  7. return;
  8. // 交换左右孩子结点
  9. TreeNode pTemp = root.left;
  10. root.left = root.right;
  11. root.right = pTemp;
  12. // 左子树不为空,递归交换左子树
  13. if (root.left != null)
  14. Mirror(root.left);
  15. // 右子树不为空,递归交换右子树
  16. if (root.right != null)
  17. Mirror(root.right);
  18. }

3.  层次遍历思想

  1. public void Mirror(TreeNode root)
  2. {
  3. if (root == null)
  4. return;
  5. // 初始化一个队列
  6. Queue<TreeNode> queue = new LinkedBlockingQueue<>();
  7. // 根结点入队列
  8. queue.add(root);
  9. // 队列不为空
  10. while (!queue.isEmpty())
  11. {
  12. TreeNode node = queue.poll();
  13. // 交换该结点的左右孩子结点
  14. if (node.left != null || node.right != null)
  15. {
  16. TreeNode tmp = node.left;
  17. node.left = node.right;
  18. node.right = tmp;
  19. }
  20. // 左子树不为空,则左子树入队列
  21. if (node.left != null)
  22. queue.add(node.left);
  23. // 右子树不为空,则右子树入队列
  24. if (node.right != null)
  25. queue.add(node.right);
  26. }
  27. }


 //  改成用栈也可以。(先根,再右子树,最后左子树)

  1. public void Mirror(TreeNode root)
  2. {
  3. if (root == null)
  4. return;
  5. // 初始化一个栈
  6. Stack<TreeNode> s = new Stack<TreeNode>();
  7. // 根结点入栈
  8. s.push(root);
  9. // 栈不空
  10. while (!s.empty())
  11. {
  12. TreeNode node = s.pop();
  13. if (node.left != null || node.right != null)
  14. {
  15. TreeNode tmp = node.left;
  16. node.left = node.right;
  17. node.right = tmp;
  18. }
  19. if (node.left != null)
  20. s.push(node.left);
  21. if (node.right != null)
  22. s.push(node.right);
  23. }
  24. }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值