演算法學習記錄十四(C++)--->二叉樹的映象

Deft_MKJing宓珂璟發表於2017-09-29

描述

操作給定的二叉樹,將其變換為源二叉樹的映象。
這裡寫圖片描述

分析

我們只需要遍歷二叉樹,然後每次訪問(輸出)一個節點的時候。交換其左右孩子即可
有遞迴和非遞迴兩個版本
其本質是相同的,就是把前序中序,後序遍歷中的列印節點的過程,程式設計交換左右子樹的過程,其中需要注意一點,就是交換後左右子樹進行了交換,再往下走的時候,往左走往右走的過程需改變,原來的向右走,現在應該是向左走

遞迴版本

/*
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 == NULL){
            return;
        }
        swap(pRoot->left,pRoot->right);
        Mirror(pRoot->left);
        Mirror(pRoot->right);

    }
};

非遞迴版本(前序)

// 前序 前序遍歷的過程中,先根,再左再右,
// 由於根後面才對左右子樹進行訪問,因此訪問順序可不交換,我們此時的訪問順序依舊是根左右,但是對應原來的根右左
class Solution {
public:
    void Mirror(TreeNode *pRoot) {
        if(pRoot == NULL){
            return;
        }
        // 棧
        stack<TreeNode *> nStack;
        // 壓根節點入棧
        nStack.push(pRoot);
        // 根節點
        TreeNode *node = pRoot;
        // 一開始棧裡面有根節點 不為空
        while(nStack.empty() != true){
            // 獲取棧頂元素
            node = nStack.top();
            nStack.pop();
            // 交換
            if(node->left != NULL || node->right != NULL){
                swap(node->left,node->right);
            }
            // 遞迴左子樹
            if(node->left != NULL){
                nStack.push(node->left);
            }
            // 遞迴右子樹
            if(node->right != NULL){
                nStack.push(node->right);
            }
        }

    }
};

非遞迴版本(中序)

class Solution {
public:
    // 中序 中序遍歷的時候,訪問順序左根右,由於訪問後,依然要向右走,
    // 所以交換後,變成了向左走 也就是最後一段程式碼的體現
    void Mirror(TreeNode *pRoot) {
        if(pRoot == NULL){
            return;
        }
        // 棧
        stack<TreeNode *> nStack;
        // 根節點
        TreeNode *node = pRoot;
        // 節點空 而且 棧為空 結束迴圈
        while(node != NULL || nStack.empty() != true){
            // 二叉樹左側所有節點入棧  例如第一次是 865
            while(node != NULL){
                nStack.push(node);
                node = node->left;
            }
            // 865一個個出棧
            while(nStack.empty() != true){
                node = nStack.top();
                // 出棧的過程中進行交換左右
                if(node->left != NULL || node->right != NULL){
                    swap(node->left,node->right);
                }
                nStack.pop();
                // 最關鍵的一句 由於左側所有節點已經左右交換完畢,因此你不會再去獲取node->right,不然你操作的又是剛才的節點
                // 應該繼續node->left的左子樹進行下一輪
                node = node->left;
            }
        }

    }
};

相關文章