二叉树的镜像(递归和循环)

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

方法一:递归

递归的终极思想是数学归纳法,我们思考递归的时候一定不要去一步一步看它执行了啥,只会更绕。我们牢牢记住,思考的方式是我们首先假设子问题都已经完美处理,我只需要处理一下最终的问题即可,子问题的处理方式与最终那个处理方式一样,但是问题规模一定要以1的进制缩小。最后给一个递归出口条件即可。

对于本题,首先假设root的左右子树已经都处理好了,即左子树自身已经镜像了,右子树自身也镜像了,那么最后一步就是交换左右子树,问题解决。所以我只需要将Root->left和Root->right交换即可。下面进入递归,就是处理子问题。子问题的处理方式与root一样,只是要缩小问题规模,所以只需要考虑Root->left是什么情况,Root->right是什么情况即可。

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    void Mirror(TreeNode *pRoot) {
        //递归中止条件
        if(pRoot == nullptr)
            return ;

        if(pRoot->left != nullptr || pRoot->right != nullptr){
            TreeNode* temp = pRoot->left;
            pRoot->left = pRoot->right;
            pRoot->right = temp;
        }

        //if(pRoot->left != nullptr)
            Mirror(pRoot->left);
        //if(pRoot->right != nullptr)
            Mirror(pRoot->right);
    }
};

方法二:循环(栈)

(1)先序遍历(根右左,DFS深度优先遍历)

用先序遍历的性质去遍历整个树。然后同时把左右子树交换 8 6 10 5 7 9 11

用一个栈,先把根节点push,然后交换他的两个儿子,然后把他的左节点压入,右节点压入,进入下一个步骤, 由于交换了位置现在在栈顶的是原来树的右节点,由于这个特殊性质,他就能再迭代下去,这栈顶就是新的节点,然后弹出再找他的左右儿子再交换,再压栈,一直这样下去,直到栈为空,二叉树的镜像转换完毕

void MirrorIteratively(BinaryTreeNode* pRoot)
{
    if(pRoot == nullptr)
        return;

    std::stack<BinaryTreeNode*> stackTreeNode;
    stackTreeNode.push(pRoot);
    while(stackTreeNode.size() > 0)	//使用!stackTreeNode.empty()更好,因为他的速度更快
    {
        BinaryTreeNode *pNode = stackTreeNode.top();
        stackTreeNode.pop();

        BinaryTreeNode *pTemp = pNode->m_pLeft;
        pNode->m_pLeft = pNode->m_pRight;
        pNode->m_pRight = pTemp;

        if(pNode->m_pLeft)
            stackTreeNode.push(pNode->m_pLeft);

        if(pNode->m_pRight)
            stackTreeNode.push(pNode->m_pRight);
    }
}

(2)广度遍历BFS

我们按照广度遍历二叉树的顺序,逐个处理遍历的节点。当处理的当前节点,如果有孩子节点,我们交换它们的孩子节点,并且把它们的非空孩子入队列。处理完当前节点以后,我们下一次处理队头的节点。

class Solution {
public:
    void Mirror(TreeNode* pRoot){
        if (pRoot == nullptr)//如果处理的空树,我们直接返回
                return;
        queue<TreeNode *> q;
        q.push(pRoot);
        
        while (!q.empty()){
            TreeNode* pNode = q.front();
            q.pop();
            
            if (pNode->left != nullptr || pNode->right != nullptr)    //非叶子节点
                swap(pNode->left,pNode->right);//交换其左右孩子
            if (pNode->left)//左孩子不为空
                q.push(pNode->left);
            if (pNode->right)//右孩子不为空
                q.push(pNode->right);
        }
    }
};
发布了65 篇原创文章 · 获赞 25 · 访问量 2629

猜你喜欢

转载自blog.csdn.net/weixin_43892514/article/details/104574802