二叉树遍历算法总结(递归与非递归)

一:前言
二叉树的遍历方法分四种:前序,中序,后序以及层次遍历。
其中,前中后遍历方法的实现分递归和非递归,非递归遍历的实现需要借助于栈。
实际上,递归的调用就是一种栈的实现,所以,非递归遍历就需要人工借助栈结构来实现。
而层次遍历需要借助队列。

二:前中后序遍历
递归遍历:
递归遍历的思想和方法很简单,通过调整输出语句来实现前,中,后三种遍历。

代码如下:

void show(BiTree T)
{
    if(T)
    {
        printf("%c ",T->data);//修改这三个语句的顺序分别实现三种遍历
        show(T->lchild);
        show(T->rchild);
    }
}

非递归遍历:

总结了5总不同的非递归遍历算法,四种思路,都需要借助栈来完成。

第一种遍历算法:
算法的思路:
1.从根结点开始,若当前结点的左孩子不为空,则遍历左孩子并进栈。
2.结点的左孩子为空时,出栈并遍历当前结点的右孩子结点
3.以右孩子结点为根结点,又沿着左孩子不断遍历,重复1.2步骤
此算法为前序遍历

void preorder1(BiTree T)//前序遍历1
{
    LinkStack s;
    InitStack(&s);
    BiTree temp;
    temp = T;
    while(temp || !EmptyStack(s)) //第一个条件temp是为了进入循环
    {
        if(temp)    //一直遍历左子树到底部
        {
            Push(&s,temp);
            printf("%c",temp->data);
            temp = temp->lchild;
        }
        else      //lchild为空,跳转到rchild
        {
            Pop(&s,&temp);
            temp = temp->rchild;
        }
    }
}

第二种遍历算法

    算法思路与第一种遍历算法一致,只是改变了遍历语句的位置,不是在进栈的时候输出,而是在出栈的时候输出,前序遍历则为中序遍历

    1.从根结点开始,当前结点左孩子不为空时,左孩子进栈。

    2.当前结点左孩子为空时,出栈并输出当前结点,然后跳转该结点的右孩子

    3.重复1,2步骤直到栈空

void inorder(BiTree T)//中序遍历 
{
    LinkStack s;
    InitStack(&s);
    BiTree temp = T;
    while(temp || !EmptyStack(s))
    {
        if(temp)
        {
            Push(&s,temp);
            temp = temp->lchild;
        }
        else
        {
            Pop(&s,&temp);
            printf("%c ",temp->data); //出栈时输出则为中序遍历
            temp = temp->rchild;
        }
    }
}

第三种遍历算法

    此种算法为前序遍历

    算法思路:1.先将根结点入栈

         2.出栈栈顶并输出,先入栈当前结点的右孩子结点,在入栈当前结点的左孩子结点

                     3.重复第2步直到栈空

void preorder2(BiTree T)
{
    LinkStack s;
    InitStack(&s);
    BiTree temp = T;
    Push(&s,temp);
    while(!EmptyStack(s))
    {
        Pop(&s,&temp);            //出栈顶并输出
        printf("%c ",temp->data);
        if(temp->rchild)        //入栈右孩子
        {
            Push(&s,temp->rchild);
        }
        if(temp->lchild)        //入栈左孩子
        {
            Push(&s,temp->lchild);
        }
    }
}

第四种遍历算法:

    后序遍历的非递归实现比较复杂,要保证输出当前结点时左右孩子结点已经输出(或者左右孩子为空)

    即每输出一个结点要满足以下两个条件之一:

    1.此结点的左右孩子为空

    2.此结点的左右孩子已经遍历

    算法思路:1.先将根结点入栈,以栈空为循环停止的条件

         2. 用结点指针pre记录上一个输出结点地址,cur记录当前结点地址

           2.1 当前结点的左右孩子为空时,或者pre记录的结点为当前结点的左(右)孩子时,出栈并输出当前结点,并更新pre

           2.2 否则按照右孩子,左孩子的顺序入栈

         3.循环第2步直到栈空

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/f3c3609af955cbff8302940b75157b8a.html