二叉树遍历(递归+非递归)

二叉树的递归很简单,但是非递归就有点复杂了。

第一种先序遍历、中序遍历、第一种后序遍历都是一直将左子树压入栈,其中先序遍历和中序遍历输出位置不同,后序遍历则需要前驱标记pre来判断右孩子是否访问过;

第二种先序遍历和第二种后序遍历是根据层序遍历的思想写的,将队列换成栈,顺序换成先入右孩子再入左孩子,但是后序遍历需要用pre判断左右孩子是否都访问过。

测试数据:AB#DF##G##CEH##I###

#include <bits/stdc++.h>
using namespace std;
struct node
{
    char data;
    node *l, *r;
};

//建立二叉树
void creat(node *&t)
{
    char c;
    cin>>c;
    if(c == '#')
    {
        t = NULL;
        return;
    }
    t = (node*)malloc(sizeof(node));
    t->data = c;
    creat(t->l);
    creat(t->r);
}

//先序遍历二叉树(递归)
void pre_di(node *t)
{
    if(!t) return;
    printf("%c ", t->data);
    pre_di(t->l);
    pre_di(t->r);
}

//中序遍历二叉树(递归)
void in_di(node *t)
{
    if(!t) return;
    in_di(t->l);
    printf("%c ", t->data);
    in_di(t->r);
}

//后序遍历二叉树(递归)
void post_di(node *t)
{
    if(!t) return;
    post_di(t->l);
    post_di(t->r);
    printf("%c ", t->data);
}

//先序遍历二叉树(非递归1)
void pre_no_di1(node *t)
{
    stack<node*>S;
    while(t || !S.empty())
    {
        if(t)
        {
            printf("%c ", t->data);
            S.push(t);
            t = t->l;
        }
        else
        {
            t= S.top();
            S.pop();
            t = t->r;
        }
    }
    cout<<endl;
}

//先序遍历二叉树(非递归2)
void pre_no_di2(node *t)
{
    stack<node*>S;
    S.push(t);
    while(!S.empty())
    {
        t = S.top();
        S.pop();
        printf("%c ", t->data);
        if(t->r) S.push(t->r);
        if(t->l) S.push(t->l);
    }
    cout<<endl;
}

//中序遍历二叉树(非递归)
void in_no_di(node *t)
{
    stack<node*>S;
    while(t || !S.empty())
    {
        if(t)
        {
            S.push(t);
            t = t->l;
        }
        else
        {
            t = S.top();
            S.pop();
            printf("%c ", t->data);
            t = t->r;
        }
    }
    cout<<endl;
}

//后序遍历二叉树(非递归1)
void post_no_di1(node *t)
{
    stack<node*>S;
    node *pre = NULL;
    while(t || !S.empty())
    {
        while(t)
        {
            S.push(t);
            t = t->l;
        }
        t = S.top();
        if(!t->r || pre == t->r)
        {
            printf("%c ", t->data);
            pre = t;
            S.pop();
            t = NULL;
        }
        else
            t = t->r;
    }
    cout<<endl;
}

//后序遍历二叉树(非递归2)
void post_no_di2(node *t)
{
    stack<node*>S;
    node *pre = NULL;//pre本来想写char类型,但是下面if里就要换成pre==t->l->data,如果t->l为空则会报错!
    S.push(t);
    while(!S.empty())
    {
        t = S.top();
        if((t->l == NULL && t->r == NULL) || (pre != NULL && (pre == t->l || pre == t->r))) //pre=t->l代表仅有左且已访问或者先访问过右又访问了左
        {
            printf("%c ", t->data);
            pre = t;
            S.pop();
        }
        else
        {
            if(t->r) S.push(t->r);
            if(t->l) S.push(t->l);
        }
    }
    cout<<endl;
}

//层序遍历
void ceng(node *t)
{
    queue<node*>Q;
    Q.push(t);
    while(!Q.empty())
    {
        t = Q.front();
        Q.pop();
        printf("%c ", t->data);
        if(t->l) Q.push(t->l);
        if(t->r) Q.push(t->r);
    }
    cout<<endl;
}

//销毁二叉树
void Free(node *&t)
{
    if(t->l) Free(t->l);
    if(t->r) Free(t->r);
    free(t);
}

int main()
{
    node *t;
    puts("请输入二叉树");
    creat(t);
    puts("创建成功");
    printf("先序遍历二叉树(递归):   ");
    pre_di(t);
    cout<<endl;
    printf("先序遍历二叉树(非递归1):");
    pre_no_di1(t);
    printf("先序遍历二叉树(非递归2):");
    pre_no_di2(t);
    printf("
中序遍历二叉树(递归):   ");
    in_di(t);
    cout<<endl;
    printf("中序遍历二叉树(非递归): ");
    in_no_di(t);
    printf("
后序遍历二叉树(递归):   ");
    post_di(t);
    cout<<endl;
    printf("后序遍历二叉树(非递归1):");
    post_no_di1(t);
    printf("后序遍历二叉树(非递归2):");
    post_no_di2(t);
    printf("
层序遍历二叉树:");
    ceng(t);
    Free(t);
    return 0;
}

运行截图:

 

原文地址:https://www.cnblogs.com/lesroad/p/8948521.html