1. 程式人生 > 實用技巧 >中序遍歷(遞迴+迭代)

中序遍歷(遞迴+迭代)

題目要求

給定一個二叉樹,返回它的中序 遍歷。

示例
輸入: [1,null,2,3]
   1
    \
     2
    /
   3

輸出: [1,3,2]

進階: 遞迴演算法很簡單,你可以通過迭代演算法完成嗎?

解答:

迭代演算法可用棧儲存曾經路過的中序結點,回溯時可用bool型變數遮蔽對左子樹的訪問,避免發生死迴圈。

程式碼及分析註釋如下:

#include<iostream>
#include<vector>
using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 };
 
//中序遍歷遞迴演算法
void inOrder(TreeNode* root, vector<int>& vi) {
    if (root != NULL) {
        inOrder(root->left, vi);
        vi.push_back(root->val);
        inOrder(root->right, vi);
    }
}
vector<int> inorderTraversal(TreeNode* root) {
    vector<int> vi;
    inOrder(root, vi);
    return vi;
}

//中序遍歷迭代演算法
vector<int> inOrderIteration(TreeNode* root) {
    vector<int> vi;
    vector<TreeNode *> stack;
    TreeNode* pT = root;
    bool backtrace = false;//回溯標誌
    while (pT != NULL)
    {
        if (backtrace==false && pT->left != NULL)
        {//若存在左子樹,指標指向左子樹
            stack.push_back(pT);
            pT = pT->left;
        }else{//不存在左子樹,先儲存當前值
            backtrace = false;//設定回溯標誌為否
            vi.push_back(pT->val);
            if (pT->right != NULL) {//若存在右子樹,指標指向右子樹
                //stack.push_back(pT);-----------此時按理說應該不用入棧
                pT = pT->right;
            }else {//若不存在右子樹,返回父節點
                if (stack.empty() == false)
                {//若棧非空,取出棧頂元素
                    pT = stack.back();
                    stack.pop_back();
                    backtrace = true;//設定回溯標記為true,這樣便能不再訪問左子樹
                }
                else//需要回溯,但棧已空,此時遍歷已結束
                    break;
            }
        }
    }
    return vi;
}

int main()
{
    TreeNode a(1), b(2), c(3), d(4), e(5), f(6), g(7), h(8), i(9), j(10);
    a.left = &b;
    a.right = &e;
    b.left = &c;
    b.right = &d;
    d.right = &f;
    e.left = &g;
    e.right = &h;
    h.left = &i;
    i.right = &j;
//    auto vi = inorderTraversal(&a);
    auto vi = inOrderIteration(&a);
    for (auto i = vi.begin(); i != vi.end(); ++i)
    {
        cout << *i << "\t";
    }
}