二叉树的前序中序后序层次遍历的递归与非递归实现

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树的前序中序后序层次遍历的递归与非递归实现相关的知识,希望对你有一定的参考价值。

二叉树的遍历有前序遍历、中序遍历、后序遍历、层次遍历等,笔者在这里总结一下各种遍历的实现。

一.前序遍历。

前序遍历访问节点顺序为:根节点->左子节点->右子节点。

递归实现如下:

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;
}

 

以上是关于二叉树的前序中序后序层次遍历的递归与非递归实现的主要内容,如果未能解决你的问题,请参考以下文章

二叉树的前序中序后序遍历-非递归-使用同一段代码实现

经典面试题二二叉树的递归与非递归遍历(前序中序后序)

二叉树的前序中序后序遍历相互求法

二叉树的前序中序后序遍历

二叉树前序中序后序遍历(非递归统一解法)

二叉树的前序中序后序层次遍历的原理及C++代码实现