二叉树3种遍历算法递归与非递归实现详解

 

一, 二叉树先序遍历的实现

  1.     递归实现
void PreOrderTraverse(BiTree T)
{


    if( T )
    {
        VisitF(T->data);//访问根节点
        PreOrderTraverse(T->lchild);//递归左子树
        PreOrderTraverse(T->rchild);//递归右子树
    }
}

    2.   非递归实现

思路: 

  1. 判断栈是否为空或子树为空
  2. 若不为空,就访问左孩子并将其入栈,直至左孩子为空
  3. 若左孩子为空,就出栈,然后访问右孩子,入栈,就这样不断的循环。

 

void PreOrderTraverse_Nonrecursion(BiTree T)
{
    LiStack  S ;
    BiTree  p ;
    S = NULL ;
    p = T ;

    InitStack(S) ;

    if(NULL == p)
    {
        printf("树为空!\n") ;
        return ;
    }

    while(p || !StackEmpty(S))
    {
        if(p)
        {
            Push(S, p) ;
            VisitF(p->data);
            p = p->lchild ;
        }
        else
        {
            Pop(S, p) ;
            p = p->rchild ;
        }
    }

    free(S) ;
}

 

 


 

二,  二叉树中序遍历的实现

 

  1.     递归实现
/*
    中序遍历二叉树
*/
void InOrderTraverse(BiTree T)
{

    if( T )
    {
        InOrderTraverse(T->lchild);
        VisitF(T->data);
        InOrderTraverse(T->rchild);
    }
}

      2.    非递归实现

思路:思路基本和先序差不多,只是输出数据的时候不一样

  1. 判断栈和树是否为空,

  2. 若不,则判断树是否为空,

  3. 不为继续将左子树进栈,若为空,则出栈,输出数据,然后访问右子树。

 

void InOrderTraverse_Nonrecursion(BiTree T)
{
    LiStack  S ;
    BiTree  p ;
    S = NULL ;
    p = T ;

    InitStack(S) ;

    if(NULL == p)
    {
        printf("树为空!\n") ;
        return ;
    }

    while(p || !StackEmpty(S))
    {
        if(p)
        {
            Push(S, p) ;

            p = p->lchild ;
        }
        else
        {
            Pop(S, p) ;
            VisitF(p->data);
            p = p->rchild ;
        }
    }

    free(S) ;
}

 


 

三,  二叉树中序遍历的实现

  1.  递归实现

 

/*
    后续遍历二叉树
*/
void PostOrderTraverse(BiTree T)
{

    if( T )
    {
        PostOrderTraverse(T->lchild);
        PostOrderTraverse(T->rchild);
        VisitF(T->data);
    }
}

 2. 非递归实现

思路 :实现有多多种方法,有两个栈,或加标志位实现,但是我觉得如下实现最容易懂

       要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。

 

void PostOrderTraverse_Nonrecursion(BiTree T)
{
    LiStack  S ;
    BiTree  cur, pre ;
    S = NULL ;
    InitStack(S) ;
    if(NULL == T)
    {
        printf("树为空!\n") ;
        return ;
    }

    pre = NULL ;
    cur = NULL ;
    Push(S,T) ;
    while(!StackEmpty(S))
    {
        cur = NULL ;
        GetTop(S,cur) ;
        if((cur->lchild == NULL && cur->rchild == NULL) || (pre != NULL && (pre == cur->lchild ||pre == cur->rchild)))
        {
            VisitF(cur->data);
            pre = cur ;
            Pop(S,cur) ;
        }
        else
        {
            if(cur->rchild != NULL)
            {
                Push(S,cur->rchild) ;
            }
            if(cur->lchild != NULL)
            {
                Push(S,cur->lchild) ;
            }
        }
    }
    free(S) ;
}

 




如下是完整代码:

 

#include<stdio.h>
#include<stdlib.h>

#define OK 1
#define ERROR -1

typedef char TElemType;

typedef int Status;

typedef struct BiTNode
{

    TElemType data;
    struct BiTNode *lchild,*rchild;

} BiTNode,*BiTree;


typedef BiTNode * StackElemType;

typedef struct LinkNode    //栈的节点
{
    StackElemType data ;
    LinkNode * next ;
} LinkNode,*LiStack;

typedef BiTNode * QueueElemType ;     //定义队列包含的数据类型

typedef struct QNode     //定义队列节点
{
    QueueElemType  data ;
    struct QNode * next ;
} QNode,*QueuePtr;

typedef struct
{
    QueuePtr fronts;
    QueuePtr rears;
} LinkQueue;



Status creatBiTree(BiTree &T);

void Visit(char ch,int level);

void PreOrderTraverse(BiTree T,int level);

void InOrderTraverse(BiTree T,int level);

void PostOrderTraverse(BiTree T,int level);

Status  InitStack(LiStack &S);

void Push(LiStack &S, StackElemType data);

void Pop(LiStack & S, StackElemType &data);

int StackEmpty(LiStack  &S);

int GetTop(LiStack &S, StackElemType & data);

Status InitQueue(LinkQueue &Q);

Status EnQueue(LinkQueue &Q, QueueElemType data);

Status DeQueue(LinkQueue &Q, QueueElemType & data);

int QueueEmpty(LinkQueue Q);

void PreOrderTraverse_Nonrecursion(BiTree T);

void InOrderTraverse_Nonrecursion(BiTree T);

void PostOrderTraverse_Nonrecursion(BiTree T);



/*********************************************************************/
/*****************************栈的方法********************************/
//栈的函数定义
Status  InitStack(LiStack &S)
{
    S = (LinkNode *)malloc(sizeof(LinkNode)) ;
    if(NULL == S)
    {
        printf("内存不足,不能分配栈!\n") ;
        exit(0) ;
    }

    S->next = NULL ;
}

void Push(LiStack &S, StackElemType data)
{
    LiStack q ;
    q = (LinkNode *)malloc(sizeof(LinkNode)) ;
    if(NULL == q)
    {
        printf("内存不足,不能分配栈!\n") ;
        exit(0) ;
    }

    /*
        插入顺序相当于头插法.
    */
    q->data = data ;
    q->next = S->next ;
    S->next = q ;
}

void Pop(LiStack & S, StackElemType &data)
{
    LiStack  q;
    if(NULL == S->next)
    {
        printf("栈为空,无返回值!\n") ;
    }

    q = S->next ;
    data = q->data ;
    S->next = q->next ;
    free(q) ;
}


int StackEmpty(LiStack  &S)
{
    if(NULL == S->next)
    {
        return(1) ;
    }

    return(0) ;
}

int GetTop(LiStack &S, StackElemType & data)
{
    if(NULL != S->next)
    {
        data = S->next->data ;
        return(1) ;
    }
    else
    {
        //data = NULL ;
        return(0) ;
    }
}

/*********************************************************************/




/*****************************队列的方法******************************/


//队列函数的定义
Status InitQueue(LinkQueue &Q)
{
    Q.fronts = Q.rears = (QNode *)malloc(sizeof(QNode)) ;
    if(NULL == Q.fronts)
    {
        printf("内存不足!\n") ;
        return ERROR;
    }

    Q.fronts->next = NULL;

}

Status EnQueue(LinkQueue &Q, QueueElemType data)
{
    QueuePtr q ;
    q = (QNode*)malloc(sizeof(QNode));

    if(NULL == q)
    {
        printf("内存不足!\n") ;
        return ERROR;
    }

    //构造q
    q->data = data ;
    q->next = NULL;


    q->next = Q.rears->next ;
    Q.rears = q ;

    return OK;
}

Status DeQueue(LinkQueue &Q, QueueElemType & data)
{
    QueuePtr  p ;
    if(Q.fronts == Q.rears)
    {
        printf("队列为空!\n") ;
        return ERROR ;
    }


    p = Q.fronts->next ;
    data = p->data ;


    Q.fronts->next = p->next ;
    if(Q.rears == p)
        Q.rears = Q.fronts ;

    free(p);

    return OK;
}

int QueueEmpty(LinkQueue Q)
{
    if(Q.fronts == Q.rears)
        return(1) ;
    else
        return(0) ;
}

/*********************************************************************/








/*
   先序创建二叉树
*/
Status creatBiTree(BiTree &T)
{
    char ch;

    scanf("%c",&ch);

    if('@' == ch)
    {
        T = NULL;
    }
    else
    {

        //申请失败
        if(!(T = (BiTNode*)malloc(sizeof(BiTNode))))
            return ERROR;

        T->data = ch;

        creatBiTree(T->lchild);
        creatBiTree(T->rchild);
    }



    return OK;
}

void VisitF(char ch)
{
    printf("%c  ",ch);
}

void Visit(char ch,int level)
{

    printf("%c 位于第 %d 层 \n",ch,level);

}


/*
    先序遍历二叉树
*/
void PreOrderTraverse(BiTree T,int level)
{



    if( T )
    {
        VisitF(T->data);
        PreOrderTraverse(T->lchild,++level);
        PreOrderTraverse(T->rchild,++level);
    }
}

void PreOrderTraverse_Nonrecursion(BiTree T)
{
    LiStack  S ;
    BiTree  p ;
    S = NULL ;
    p = T ;

    InitStack(S) ;

    if(NULL == p)
    {
        printf("树为空!\n") ;
        return ;
    }

    while(p || !StackEmpty(S))
    {
        if(p)
        {
            Push(S, p) ;
            VisitF(p->data);
            p = p->lchild ;
        }
        else
        {
            Pop(S, p) ;
            p = p->rchild ;
        }
    }

    free(S) ;
}


/*
    中序遍历二叉树
*/
void InOrderTraverse(BiTree T)
{

    if( T )
    {
        InOrderTraverse(T->lchild);
        VisitF(T->data);
        InOrderTraverse(T->rchild);
    }
}

void InOrderTraverse_Nonrecursion(BiTree T)
{
    LiStack  S ;
    BiTree  p ;
    S = NULL ;
    p = T ;

    InitStack(S) ;

    if(NULL == p)
    {
        printf("树为空!\n") ;
        return ;
    }

    while(p || !StackEmpty(S))
    {
        if(p)
        {
            Push(S, p) ;

            p = p->lchild ;
        }
        else
        {
            Pop(S, p) ;
            VisitF(p->data);
            p = p->rchild ;
        }
    }

    free(S) ;
}


/*
    后续遍历二叉树
*/
void PostOrderTraverse(BiTree T)
{

    if( T )
    {
        PostOrderTraverse(T->lchild);
        PostOrderTraverse(T->rchild);
        VisitF(T->data);
    }
}

void PostOrderTraverse_Nonrecursion(BiTree T)
{
    LiStack  S ;
    BiTree  cur, pre ;
    S = NULL ;
    InitStack(S) ;
    if(NULL == T)
    {
        printf("树为空!\n") ;
        return ;
    }

    pre = NULL ;
    cur = NULL ;
    Push(S,T) ;
    while(!StackEmpty(S))
    {
        cur = NULL ;
        GetTop(S,cur) ;
        if((cur->lchild == NULL && cur->rchild == NULL) || (pre != NULL && (pre == cur->lchild ||pre == cur->rchild)))
        {
            VisitF(cur->data);
            pre = cur ;
            Pop(S,cur) ;
        }
        else
        {
            if(cur->rchild != NULL)
            {
                Push(S,cur->rchild) ;
            }
            if(cur->lchild != NULL)
            {
                Push(S,cur->lchild) ;
            }
        }
    }
    free(S) ;
}

int main()
{
    int level = 1;
    BiTree T = NULL;

    creatBiTree(T);

    printf("先序遍历二叉树,每个结点在第几行\n");
    PreOrderTraverse(T,level);

    printf("\n\n");
    printf("先序遍历二叉树,非递归算法\n");

    PreOrderTraverse_Nonrecursion(T);
    printf("\n\n\n");

    /***************************************************/


    printf("中序遍历二叉树\n");
    InOrderTraverse(T);

    printf("\n\n");
    printf("中序遍历二叉树,非递归算法\n");

    InOrderTraverse_Nonrecursion(T);
    printf("\n\n\n");

    /***************************************************/

    printf("后序遍历二叉树\n");
    PostOrderTraverse(T);

    printf("\n\n");
    printf("后序遍历二叉树,非递归算法\n");

    PostOrderTraverse_Nonrecursion(T);
    printf("\n\n\n");

    return 0;
}

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值