樹的面試題(一):二叉樹的鏡像


關於二叉樹

  二叉樹是一種在面試中也會涉及的到數據結構。

  一棵二叉樹是結點的一個有限集合,該集合或者為空,或者是由一個根結點加上兩棵分別稱為左子樹和右子樹的、互不相交的二叉樹組成。二叉樹的物種不同的形態如下:

二叉樹的結構定義有三個部分組成,分別是值域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,只有一個結點,普通二叉樹,二叉樹所有結點只有左結點/右結點等。針對下面幾種情況都要滿足需求。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM