二叉树前序(先序)中序后序遍历 C++递归和非递归实现

如下图,对图中二叉树遍历:

先序为:ABDNCEFGHIJKLMOQP
中序为:DNBCGFEAHJKILOQMP
后序为:NDGFECBKJQOPMLIHA

《二叉树前序(先序)中序后序遍历 C++递归和非递归实现》 二叉树示意.jpg

假设树节点如下:

struct Node{
    char data;
    Node *left;
    Node *right;
};

递归实现

先序

void preOrder(Node *root){
    cout<<root->data;
    preOrder(root->left);
    preOder(root->right);
}

中序

void inOrder(Node *root){
    preOrder(root->left);
    cout<<root->data;
    preOder(root->right);
}

后序

void postOrder(Node *root){
    preOrder(root->left);
    preOder(root->right);
    cout<<root->data;
}

非递归实现

先序

对于任一结点P:
1)访问结点P,并将结点P入栈;
2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P;
3)直到P为NULL并且栈为空,则遍历结束。

void preOrderS(Node *root)   
{
    stack<Node*> s;
    Node *p=root;
    while(p!=NULL||!s.empty())
    {
        while(p!=NULL)
        {
            cout<<p->data<<" ";
            s.push(p);
            p=p->left;
        }
        if(!s.empty())
        {
            p=s.top();
            s.pop();
            p=p->right;
        }
    }
}

中序

对于任一结点P,
1)若其左孩子不为空,则将P入栈并将P的左孩子置为当前的P,然后对当前结点P再进行相同的处理;
2)若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将当前的P置为栈顶结点的右孩子;
3)直到P为NULL并且栈为空则遍历结束。

void inOrderS(Node *root){
    stack<Node*> s;
    Node *p=root;
    while(p!=NULL||!s.empty()){
        while(p!=NULL)){
            s.push(p);
            p=p->left;
        }
        if(!s.empty()){
            p=s.top();
            s.pop();
            cout<<p->data;
            p=p->right;
        }
    }
}

后序

因为后序非递归遍历二叉树的顺序是先访问左子树,再访问右子树,最后访问根节点。当用堆栈来存储节点,必须分清返回根节点时,是从左子树返回的,还从右子树返回的。所以,使用辅助指针r,其指向最近访问过的节点。也可以在节点中增加一个标志域,记录是否已被访问。

void PostOrderS(Node *root) {
    Node *p = root, *r = NULL;
    stack<Node*> s;
    while (p!=NULL || !s.empty()) {
        if (p!=NULL) {//走到最左边
            s.push(p);
            p = p->left;
        }
        else {
            p = s.top();
            if (p->right!=NULL && p->right != r)//右子树存在,未被访问
                p = p->right;
            else {
                s.pop();
                visit(p->val);
                r = p;//记录最近访问过的节点
                p = NULL;//节点访问完后,重置p指针
            }
        }//else
    }//while
}
    原文作者:shu2man
    原文地址: https://www.jianshu.com/p/6a1c47b5ac49
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞