• 二叉树的非递归遍历与层次遍历


    二叉树的递归遍历很好写,也很好理解。但因为是递归程序,不可避免地需要调用系统栈,耗时较长,这里我们来探究一下二叉树的非递归遍历的算法。这种方法需要使用栈这种数据结构,这里关于栈的一些操作函数可以看成伪代码吧,先给出线序、中序、后序遍历的代码即说明。

    先序遍历:

     1 void PreOrderTraverse(BinTree b)
     2 {
     3     InitStack(S);///初始化创建栈
     4     BinTree p=b;///p为工作指针
     5     while(p||!isEmpty(s))
     6     {
     7         while(p)///到最左下的孩子
     8         {
     9             printf(" %c ",p->date);///先序先遍历结点
    10             Push(S,p);///入栈
    11             p=p->lchild;
    12         }
    13         if(!isEmpty(s))///在栈不为空的情况下,左孩子为空,弹出该结点,遍历右孩子
    14         {
    15             p=Pop(s);
    16             p=p->rchild;
    17         }
    18     }
    19 }

     再给出使用数组模拟的函数

     1 void Preorder_n(BiTree bt)  /*先序遍历的非递归算法*/
     2 {
     3     BiTree stack[MAX],p;
     4     int top=0,i;
     5     for(i=0; i<MAX; i++)
     6     {
     7         stack[i]=NULL; /*初始化栈*/
     8     }
     9     p=bt;
    10     do
    11     {
    12         while(p)
    13         {
    14              printf("%c",p->data);
    15              stack[top++]=p;
    16              p=p->lchild;
    17         }
    18         if(top!=0)
    19         {
    20             p=stack[top-1];//去栈底
    21             top--;//出栈
    22             p=p->rchild;
    23         }
    24     }while(top!=0||p!=NULL);
    25 }
    View Code

    中序遍历:

    void InOrderTraverse(BinTree b)
    {
        InitStack(S);///初始化创建栈
        BinTree p=b;///p为工作指针
        while(p||!isEmpty(s))
        {
            while(p)
            {
                Push(S,p);///中序现将结点进栈保存
                p=p->lchild;
            }///遍历到左下角尽头再出栈访问
            if(!isEmpty(s))///在栈不为空的情况下,左孩子为空,弹出该结点,遍历右孩子
            {
                p=Pop(s);
                printf(" %c ",p->data);
                p=p->rchild;///遍历右孩子
            }
        }
    }

     再给出使用数组模拟的函数

     1 void InOrder_n(BiTree bt)  /*中序遍历的非递归算法*/
     2 {
     3     BiTree stack[MAX],p;
     4     int top=0,i;
     5     for(i=0; i<MAX; i++)
     6     {
     7         stack[i]=NULL; /*初始化栈*/
     8     }
     9     p=bt;
    10     do
    11     {
    12         while(p)//顺着左链走到尽头
    13         {
    14             stack[top++]=p;
    15             p=p->lchild;
    16         }
    17         if(top>0)
    18         {
    19             p=stack[top-1];
    20             printf("%c",stack[top-1]->data);
    21             top--;
    22             p=p->rchild;
    23         }
    24     }while(top!=0||p);
    25 }
    View Code


    后序遍历:后序遍历较前两种遍历方法比较难实现,原因在于需要遍历完左子树,遍历完右子树,最后才去访问根节点。这样栈顶结点可能会从他的左子树返回,也有可能从他的右子树返回,需要区分这种情况,如果是第一次从左子树返回,那么还需要去遍历其右子树,如果是从右子树返回,那么直接返回该结点就可以了。这里使用辅助指针来区分来源。

    void PostOrderTraverse(BinTree b)
    {
        InitStack(S);///初始化创建栈
        BinTree p=b, r=NULL;///p为工作指针,辅助指针r
        while(p||!isEmpty(s))
        {
            if(p)///从根节点到最左下角的左子树都入栈
            {
                Push(S,p);///中序现将结点进栈保存
                p=p->lchild;
            }
            else
            {
                GetTop(S,p);///取栈顶,注意!不是出栈!
                if(p->rchild&&p->rchild!=r)///1.右子树还没有访问并且右子树不空,第一次栈顶
                {
                    p=p->rchild;///进入右子树
                }
                else///右子树已经访问或为空,接下来出栈访问结点,第二次栈顶
                {
                    p=Pop(s);
                    printf(" %c ",p->data);
                    r=p;///指向访问过的右子树结点
                    p=NULL;///使p为空继续访问栈顶
                }
            }
        }
    }

     数组模拟:

     1 void PostOrder_n(BiTree bt)
     2 {
     3     BiTree stack[MAX],p,r;
     4     int top=0,i;
     5     for(i=0; i<MAX; i++)
     6     {
     7         stack[i]=NULL; /*初始化栈*/
     8     }
     9     p=bt, r=NULL;///p为工作指针,辅助指针r
    10     do
    11     {
    12         if(p)///从根节点到最左下角的左子树都入栈
    13         {
    14             stack[top++]=p;///中序现将结点进栈保存
    15             p=p->lchild;
    16         }
    17         else
    18         {
    19             p=stack[top-1];///取栈顶,注意!不是出栈!
    20             if(p->rchild&&p->rchild!=r)///1.右子树还没有访问并且右子树不空,第一次栈顶
    21             {
    22                 p=p->rchild;///进入右子树
    23             }
    24             else///右子树已经访问或为空,接下来出栈访问结点,第二次栈顶
    25             {
    26                 top--;
    27                 printf("%c",p->data);
    28                 r=p;///指向访问过的右子树结点
    29                 p=NULL;///使p为空继续访问栈顶
    30             }
    31         }
    32     } while(p||top!=0);
    33 }
    View Code

    层次遍历:

    从二叉树的第一层(根节点)开始,从上至下逐层遍历,在每一层中又按照从左到右的顺序对结点逐个遍历。我们可以看出如果某个结点比同一层的先遍历,其孩子也将比其同层的孩子结点先遍历,这种先进先出的方式,不就是队列这种数据结构吗?

     1 void LevelOrder(BiTree b)
     2 {
     3     InitQueue(Q);///初始化建立队列
     4     BinTree p;
     5     EnQueue(Q,b);///根节点入队
     6     while(!isEmpty(Q))///队列不空循环
     7     {
     8         DeQueue(Q,p);///队头元素出队
     9         printf(" %c ",p->data);
    10         ///左右孩子入队
    11         if(p->lchild!=NULL)
    12         {
    13             EnQueue(Q,p->lchild);
    14         }
    15         if(p->rchild!=NULL)
    16         {
    17             EnQueue(Q,p->rchild);
    18         }
    19     }
    20 }

     使用C++ STL库 queue 的函数:

     1 void LevelOrder(BiTree p)
     2 {
     3     queue<BiTree>Q;//使用C++ STL库
     4     Q.push(p);//根节点入队
     5     while(!Q.empty())//队列不空循环
     6     {
     7         p=Q.front();//取对头
     8         printf("%c",p->data);//左右孩子入队
     9         if(p->lchild!=NULL)
    10         {
    11             Q.push(p->lchild);
    12         }
    13         if(p->rchild!=NULL)
    14         {
    15             Q.push(p->rchild);
    16         }
    17         Q.pop();//队头元素出队
    18     }
    19     printf("
    ");
    20 }
    View Code
  • 相关阅读:
    小米2/2S 手机由 Smartisan OS ROM 刷回 MIUI 教程
    Java构造和解析Json数据的两种方法详解二
    python-数据类型(上):数字、布尔值、字符串、字典
    python的介绍与安装
    PyCharm快捷键
    PyCharm安装模块
    PyCharm安装
    mac如何获取文件路径
    mac常用快捷键
    linux常用命令
  • 原文地址:https://www.cnblogs.com/wkfvawl/p/9901462.html
Copyright © 2020-2023  润新知