1. 程式人生 > 其它 >nrf52832藍芽開發踩過的坑

nrf52832藍芽開發踩過的坑

二叉樹的迭代遍歷

題目連結

144.二叉樹的前序遍歷(簡單)

94.二叉樹的中序遍歷(簡單)

145.二叉樹的後序遍歷(簡單)

題解

用迭代法(非遞迴的方式)來實現二叉樹的前中後序遍歷。

遞迴的實現就是:每一次遞迴呼叫都會把函式的區域性變數、引數值和返回地址等壓入呼叫棧中,然後遞迴返回的時候,從棧頂彈出上一次遞迴的各項引數,所以這就是遞迴為什麼可以返回上一層位置的原因。

前序遍歷(迭代法)

思路:前序遍歷是中左右,每次先處理的是中間節點,那麼先將根節點放入棧中,然後將右孩子加入棧,再加入左孩子。這樣才能保證出棧時的順序是中左右。如下所示:

程式碼(C++):

//二叉樹的前序遍歷(迭代)
class
Solution1 { public: vector<int> preorderTraversal(TreeNode *root) { //先定義一個棧,棧中存放元素的型別為指向樹節點的指標 stack<TreeNode*> sta; //再定義一個vector,用於存放結果 vector<int> result; if (root == nullptr) return result; else sta.push(root); while (!sta.empty()) { result.push_back(sta.top()
->val); // TreeNode *node = sta.top(); sta.pop(); //注意左節點或右節點為空時是不入棧的 if(node->right != nullptr) sta.push(node->right); // if(node->left != nullptr) sta.push(node->left); // } return result; } };

分析:

  • 時間複雜度:O(n),其中 n 是二叉樹的節點數

  • 空間複雜度:O(n),為迭代過程中顯式棧的開銷,平均情況下為 O(logn),最壞情況下樹呈現鏈狀,為 O(n)。

中序遍歷(迭代法)

思路:

不能直接改一下上面前序遍歷程式碼的順序來實現中序遍歷。

在上面的前序遍歷中有兩個操作:

  1. 處理:將元素放進result陣列中

  2. 訪問:遍歷節點

前序遍歷的順序是中左右,先訪問的元素是中間節點,要處理的元素也是中間節點,所以能寫出相對簡潔的程式碼,因為要訪問的元素和要處理的元素順序是一致的,都是中間節點。

而中序遍歷是左中右,先訪問的是二叉樹頂部的節點,然後一層一層向下訪問,直到到達樹左面的最底部,再開始處理節點(也就是在把節點的數值放進result陣列中),這就造成了處理順序和訪問順序是不一致的。

那麼在使用迭代法寫中序遍歷,就需要借用指標的遍歷來幫助訪問節點,棧則用來處理節點上的元素。如下所示:

程式碼(C++):

//二叉樹的中序遍歷(迭代)
class Solution2 {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        stack<TreeNode*> sta;
        vector<int> result;
        TreeNode* node = root;
        while (node != nullptr || !sta.empty()) {
            if (node != nullptr) {
                sta.push(node);
                node = node->left;
            } else {
                node = sta.top();
                sta.pop();
                result.push_back(node->val);
                node = node->right;
            }
        }
        return result;
    }
};

分析:

  • 時間複雜度:O(n),其中 n 為二叉樹節點的個數。

  • 空間複雜度:O(n),空間複雜度取決於棧深度,最壞情況下樹呈現鏈狀,為 O(n)。

後序遍歷(迭代法)

思路:先序遍歷是中左右,後續遍歷是左右中,那麼只需要調整一下先序遍歷的程式碼順序,就變成中右左的遍歷順序,然後在反轉result陣列,輸出的結果順序就是左右中了,如下圖:

程式碼(C++):

//二叉樹的後序遍歷(迭代)
class Solution3 {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*> sta;
        vector<int> result;
        if (root == nullptr) return result;
        else sta.push(root);
        while (!sta.empty()) {
            TreeNode* node = sta.top();
            sta.pop();
            result.push_back(node->val);
            if(node->left != nullptr) sta.push(node->left);
            if(node->right != nullptr) sta.push(node->right);
        }
        reverse(result.begin(), result.end());
        return result;
    }
};

分析:

  • 時間複雜度:O(N)

  • 空間複雜度:O(N)(最壞情況下)

參考連結

程式碼隨想錄