树的面试题(一):二叉树的镜像

关于二叉树

  二叉树是一种在面试中也会涉及的到数据结构。

  一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根结点加上两棵分别称为左子树和右子树的、互不相交的二叉树组成。二叉树的物种不同的形态如下:

二叉树的结构定义有三个部分组成,分别是值域val和指向左右孩子的指针*left和*right。

1 struct TreeNode {
2     int val;
3     struct TreeNode *left;
4     struct TreeNode *right;
5     TreeNode(int x) :
6             val(x), left(NULL), right(NULL) {
7     }
8 };

面试题:二叉树的镜像

 输入二叉树,输出它的镜像。

分析:

树的镜像不是我们所熟知的内容,通常在课本上所熟悉的就是树的遍历等基本的操作。但是我们可以通过图像来把镜像的过程给描述出来。比如像下面的两个二叉树就是互为镜像。

下面我们来分析,镜像发生的过程是怎么样的。

这两个树根结点都是1,那么先交换根结点的左右结点,得到图2。交换后,我们发现,对于结点2和3来说,它们的子结点的左右顺序没有发生变化。因此还要交换对应的结点。对于根结点的左子树,将其视为一棵新的二叉树,同样的交换其子结点。得到图3。同样的作用于右子树,那么最后的交换就完成了。

总结上面的几个步骤:我们先先序遍历这个树的子结点,如果子结点有子结点,那么就交换,当交换完成所有的非叶子结点,那么就是我们所要求的镜像。

递归方法

从上面的分析可以看出,递归是解决该问题比较明晰的思路,思考起来也比较能够想到。下面是递归的解决方案。

 1 void MirrorRecursively(TreeNode *pRoot)
 2 {
 3     if((pRoot == NULL) || (pRoot->left == NULL && pRoot->right))
 4         return;
 5 
 6     TreeNode *pTemp = pRoot->left;
 7     pRoot->left = pRoot->right;
 8     pRoot->right = pTemp;
 9     
10     if(pRoot->left)
11         MirrorRecursively(pRoot->left);  
12 
13     if(pRoot->right)
14         MirrorRecursively(pRoot->right); 
15 }

非递归方法

扩展一下如果,采用循环,如何实现?递归的实现借助于栈,那么循环,利用栈即可。下面给出代码。

void MirrorIteratively(TreeNode* pRoot)
{
    if(pRoot == NULL)
        return;

    std::stack<TreeNode*> stackTreeNode;
    stackTreeNode.push(pRoot);

    while(stackTreeNode.size() > 0)
    {
        TreeNode *pNode = stackTreeNode.top();
        stackTreeNode.pop();

        TreeNode *pTemp = pNode->left;
        pNode->left = pNode->right;
        pNode->right = pTemp;

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

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

 测试用例

  写代码的时候要考虑到各种情况。包括NULL,只有一个结点,普通二叉树,二叉树所有结点只有左结点/右结点等。针对下面几种情况都要满足需求。

posted @ 2016-07-24 17:25  csbdong  阅读(10063)  评论(0编辑  收藏  举报