1. 程式人生 > >二叉樹的前序、中序、後序、層次遍歷的遞迴與非遞迴實現

二叉樹的前序、中序、後序、層次遍歷的遞迴與非遞迴實現

二叉樹的遍歷有前序遍歷、中序遍歷、後序遍歷、層次遍歷等,筆者在這裡總結一下各種遍歷的實現。

一.前序遍歷。

前序遍歷訪問節點順序為:根節點->左子節點->右子節點。

遞迴實現如下:

void preorder(TreeNode* root, vector<int>& nodes) {
    if (!root) return;
    nodes.push_back(root -> val);
    preorder(root -> left, nodes);
    preorder(root -> right, nodes);
}
vector<int> preorderTraversal(TreeNode* root) {
    vector<int> nodes;
    preorder(root, nodes);
    return nodes;
} 

非遞迴實現(使用棧)如下:

對於任一結點P:

     ①訪問結點P,並將結點P入棧;

     ②判斷結點P的左孩子是否為空,若為空,則取棧頂結點並進行出棧操作,並將棧頂結點的右孩子置為當前的結點P,迴圈至①;若不為空,則將P的左孩子置為當前的結點P;

     ③直到P為NULL並且棧為空,則遍歷結束。

vector<int> preorderTraversal(TreeNode *root) {
    vector<int> v;
    if (root == NULL) return v;
    stack<TreeNode*> s;
    TreeNode* temp = root;
    while (temp != NULL || !s.empty()) {
        while (temp != NULL) {
            v.push_back(temp->val);
            s.push(temp);
            temp = temp->left;
        }
        if (!s.empty()) {
            temp = s.top();
            s.pop();
            temp = temp->right;
        }
    }
    return v;
}

二.中序遍歷。

中序遍歷訪問節點順序為:左子節點->根節點->右子節點。

遞迴實現如下:

void inorder(TreeNode* root, vector<int>& nodes) {
    if (!root) return;
    inorder(root -> left, nodes);
    nodes.push_back(root -> val);
    inorder(root -> right, nodes);
}
vector<int> inorderTraversal(TreeNode* root) {
    vector<int> nodes;
    inorder(root, nodes);
    return nodes;
} 

非遞迴實現(使用棧)如下:

對於任一結點P,

①若其左孩子不為空,則將P入棧並將P的左孩子置為當前的P,然後對當前結點P再進行相同的處理;

②若其左孩子為空,則取棧頂元素並進行出棧操作,訪問該棧頂結點,然後將當前的P置為棧頂結點的右孩子;

③直到P為NULL並且棧為空則遍歷結束

vector<int> inorderTraversal(TreeNode *root) {
    vector<int> v;
    if (root == NULL) return v;
    stack<TreeNode*> s;
    TreeNode *temp = root;
    while (temp != NULL || !s.empty()) {
        while (temp != NULL) {
            s.push(temp);
            temp = temp->left;
        }
        if (!s.empty()) {
            temp = s.top();
            s.pop();
            v.push_back(temp->val);
            temp = temp->right;
        }
    }
    return v;        
}

三.後序遍歷。

後序遍歷訪問節點順序為:左子節點->右子節點->根節點。

遞迴實現如下:

void postorder(TreeNode* root, vector<int>& nodes) {
    if (!root) return;
    postorder(root -> left, nodes);
    postorder(root -> right, nodes);
    nodes.push_back(root -> val);
}
vector<int> postorderTraversal(TreeNode* root) {
    vector<int> nodes;
    postorder(root, nodes);
    return nodes;
} 

非遞迴實現(使用棧)如下:
vector<int> postorderTraversal(TreeNode *root) {
    vector<int> v;
    stack<TreeNode*> s;
    TreeNode * curr = root;
    TreeNode * previsited = NULL;
    while (curr != NULL || !s.empty()) {
        while (curr != NULL) {
            s.push(curr);
            curr = curr->left;
        }
        curr = s.top();
        // 當前節點的右孩子如果為空或者已經被訪問,則訪問當前節點
        if (curr->right == NULL || curr->right == previsited) {
            v.push_back(curr->val);
            previsited = curr;
            s.pop();
            curr = NULL;
        }
        else curr = curr->right; //否則訪問右孩子
    }
    return v;
}

四.層次遍歷。

使用佇列:

vector<vector<int>> levelOrder(TreeNode *root) {
    queue<TreeNode*> q;
    int count = 0;
    vector<int> v;
    vector<vector<int>> v2;
    if (root == NULL) return v2;
    q.push(root);
    count++;
    int count2 = 1;
    while (!q.empty()) {
        count = count2;
        count2 = 0;
        v.clear();
        for (int i = 0; i < count; i++) {
            TreeNode * top = q.front();
            v.push_back(top->val);
            if (top->left != NULL) {
                q.push(top->left);
                count2++;
            }
            if (top->right != NULL) {
                q.push(top->right);
                count2++;
            }
            q.pop();
        }
        v2.push_back(v);
    }
    return v2;
}