目录
 2.中序遍历二叉树:" > 2.中序遍历二叉树:
首页 常见问题 二叉树的遍历算法

二叉树的遍历算法

Jun 20, 2019 am 11:51 AM
二叉树 算法 遍历

二叉树的遍历算法

 A.  二叉树的遍历 

   1.前序遍历二叉树:

        (1)若二叉树为空,则为空操作,返回空。
        (2)访问根结点。
        (3)前序遍历左子树。
        (4)前序遍历右子树。

     a.二叉树前序遍历的递归算法:

   void PreOrderTraverse(BiTree BT)
   {     if(BT)
     {
        printf("%c",BT->data);              //访问根结点
        PreOrderTraverse(BT->lchild);       //前序遍历左子树
        PreOrderTraverse(BT->rchild);       //前序遍历右子树     }
   }
登录后复制

    b.使用栈存储每个结点右子树的二叉树前序遍历的非递归算法:

      (1)当树为空时,将指针p指向根结点,p为当前结点指针。
      (2)先访问当前结点p,并将p压入栈S中。
      (3)令p指向其左孩子。
      (4)重复执行步骤(2)、(3),直到p为空为止。
      (5)从栈S中弹出栈顶元素,将p指向此元素的右孩子。
      (6)重复执行步骤(2)~(5),直到p为空并且栈S也为空。
      (7)遍历结束。
      使用栈的前序遍历的非递归算法:

      void PreOrderNoRec(BiTree BT)
      {
        stack S;
        BiTree p=BT->root;        while((NULL!=p)||!StackEmpty(S))
        {          if(NULL!=p)
          {
            printf("%c",p->data);
            Push(S,p);
            p=p->lchild;
          }          else
          {
            p=Top(S);
            Pop(S);
            p=p->rchild;
          }
        }
      }
登录后复制

    c.使用二叉链表存储的二叉树前序遍历非递归算法:

    void PreOrder(pBinTreeNode pbnode)
    {
      pBinTreeNode stack[100];
      pBinTreeNode p;      int top;
      top=0;
      p=pbnode;      do
      {        while(p!=NULL)
        {
          printf("%d\n",p->data);      //访问结点p
          top=top+1;
          stack[top]=p;
          p=p->llink;                  //继续搜索结点p的左子树        }        if(top!=0)
        {
          p=stack[top];
          top=top-1;
          p=p->rlink;                  //继续搜索结点p的右子树        }
      }while((top!=0)||(p!=NULL));
    }
登录后复制

 2.中序遍历二叉树:

      (1)若二叉树为空,则为空操作,返回空。
      (2)中序遍历左子树。
      (3)访问根结点。
      (4)中序遍历右子树。
   a.二叉树中序遍历的递归算法:
    void InOrderTraverse(BiTree BT)
    {      if(BT)
      {
         InOrderTraverse(BT->lchild);        //中序遍历左子树
         printf("%c",BT->data);              //访问根结点
         InOrderTraverse(BT->rchild);        //中序遍历右子树      }
    }
登录后复制

  b.使用栈存储的二叉树中序遍历的非递归算法:

      (1)当树为空时,将指针p指向根结点,p为当前结点指针。
     (2)将p压入栈S中,并令p指向其左孩子。
     (3)重复执行步骤(2),直到p为空。
     (4)从栈S中弹出栈顶元素,将p指向此元素。
     (5)访问当前结点p,并将p指向其右孩子。
     (6)重复执行步骤(2)~(5),直到p为空并且栈S也为空。
     (7)遍历结束。
     使用栈的中序遍历的非递归算法:
     void IneOrderNoRec(BiTree BT)
     {
       stack S;
       BiTree p=BT->root;       while((NULL!=p)||!StackEmpty(S))
       {         if(NULL!=p)
         {
           Push(S,p);
           p=p->lchild;
         }         else
         {
           p=Top(S);
           Pop(S);
           printf("%c",p->data);
           p=p->rchild;
         }
       }
     }
登录后复制

    c.使用二叉链表存储的二叉树中序遍历非递归算法:

    void InOrder(pBinTreeNode pbnode)
    {
         pBinTreeNode stack[100];
         pBinTreeNode p;         int top;
         top=0;
         p=pbnode;         do
         {           while(p!=NULL)
           {
             top=top+1;
             stack[top]=p;                //结点p进栈
             p=p->llink;                  //继续搜索结点p的左子树           }           if(top!=0)
           {
             p=stack[top];                //结点p出栈
             top=top-1;
             printf("%d\n",p->data);      //访问结点p
             p=p->rlink;                  //继续搜索结点p的右子树           }
         }while((top!=0)||(p!=NULL));
    }
登录后复制

  3.后序遍历二叉树:

      (1)若二叉树为空,则为空操作,返回空。
      (2)后序遍历左子树。
      (3)后序遍历右子树。
      (4)访问根结点。
     a.二叉树后序遍历的递归算法:
     void PostOrderTraverse(BiTree BT)
     {       if(BT)
       {
          PostOrderTraverse(BT->lchild);        //后序遍历左子树
          PostOrderTraverse(BT->rchild);        //后序遍历右子树
          printf("%c",BT->data);                //访问根结点       }
     }
登录后复制

     b.使用栈存储的二叉树后序遍历的非递归算法:

      算法思想:首先扫描根结点的所有左结点并入栈,然后出栈一个结点,扫描该结点的右结点并入栈,再扫描该右结点的所有左结点并入栈,当一个结点的左、右子树均被访问后再访问该结点。因为在递归算法中,左子树和右子树都进行了返回,因此为了区分这两种情况,还需要设置一个标识栈tag,当tag的栈顶元素为0时表示从左子树返回,为1表示从右子树返回。
       (1)当树为空时,将指针p指向根结点,p为当前结点指针。
       (2)将p压入栈S中,0压入栈tag中,并令p指向其左孩子。
       (3)重复执行步骤(2),直到p为空。
       (4)如果tag栈中的栈顶元素为1,跳至步骤(6)。
       (5)如果tag栈中的栈顶元素为0,跳至步骤(7)。
       (6)将栈S的栈顶元素弹出,并访问此结点,跳至步骤(8)。
       (7)将p指向栈S的栈顶元素的右孩子。
       (8)重复执行步骤(2)~(7),直到p为空并且栈S也为空。
       (9)遍历结束。
        使用栈的后序遍历非递归算法:

       void PostOrderNoRec(BiTree BT)
       {
         stack S;
         stack tag;
         BiTree p=BT->root;         while((NULL!=p)||!StackEmpty(S))
         {           while(NULL!=p)
           {
             Push(S,p);
             Push(tag,0);
             p=p->lchild;
           }           if(!StackEmpty(S))
           {             if(Pop(tag)==1)
             {
               p=Top(S);
               Pop(S);
               printf("%c",p->data);
               Pop(tag);    //栈tag要与栈S同步             }             else
             {
               p=Top(S);               if(!StackEmpty(S))
               {
                 p=p->rchild;
                 Pop(tag);
                 Push(tag,1);
               }
             }
           }
         }
       }
登录后复制

     c.使用二叉链表存储的二叉树后序遍历非递归算法:

     void PosOrder(pBinTreeNode pbnode)
     {
          pBinTreeNode stack[100];       //结点的指针栈          int count[100];                //记录结点进栈次数的数组          pBinTreeNode p;          int top;
          top=0;
          p=pbnode;          do
          {            while(p!=NULL)
            {
              top=top+1;
              stack[top]=p;                //结点p首次进栈
              count[top]=0;
              p=p->llink;                  //继续搜索结点p的左子树            }
            p=stack[top];                  //结点p出栈
            top=top-1;            if(count[top+1]==0)
            {
              top=top+1;
              stack[top]=p;                //结点p首次进栈
              count[top]=1;
              p=p->rlink;                  //继续搜索结点p的右子树            }            else
            {
              printf("%d\n",p->data);      //访问结点p
              p=NULL;
            }
          }while((top>0));
     }
登录后复制

 B 线索化二叉树:

       线索化二叉树的结点结构图:
                 20160409161658682.jpg
     线索化二叉树的结点类型说明:
      typedef struct node
      {
        DataType data;        struct node *lchild, *rchild;       //左、右孩子指针        int ltag, rtag;                     //左、右线索
      }TBinTNode;         //结点类型
      typedef TBinTNode *TBinTree;
登录后复制
     在线索化二叉树中,一个结点是叶子结点的充分必要条件是其左、右标志均为1.
    中序线索化二叉树及其对应的线索链表如下图:
            20160409161910151.jpg

   (1)中序线索化二叉树的算法:

   void InOrderThreading(TBinTree p)
      {        if(p)
        {
          InOrderThreading(p->lchild);   //左子树线索化          if(p->lchild)
            p->ltag=0;          else
            p->ltag=1;          if(p->rchild)
            p->rtag=0;          else
            p->rtag=1;          if(*(pre))      //若*p的前驱*pre存在          {            if(pre->rtag==1)
              pre->rchild=p;            if(p->ltag==1)
              p->lchild=pre;
          }
          pre=p;                         //另pre是下一访问结点的中序前驱
          InOrderThreading(p->rchild);   //右子树线索化        }
      }
登录后复制

   (2)在中序线索化二叉树下,结点p的后继结点有以下两种情况:

      ①结点p的右子树为空,那么p的右孩子指针域为右线索,直接指向结点p的后继结点。
     ②结点p的右子树不为空,那么根据中序遍历算法,p的后继必是其右子树中第1个遍历到的结点。
     中序线索化二叉树求后继结点的算法:
 TBinTNode *InOrderSuc(BiThrTree p)
    {
       TBinTNode *q;       if(p->rtag==1)   //第①情况         return p->rchild;       else            //第②情况       {
         q=p->rchild;         while(q->ltag==0)
           q=q->lchild;         return q;
       }
    }
登录后复制

     中序线索化二叉树求前驱结点的算法:

TBinTNode *InOrderPre(BiThrTree p)
    {
       TBinTNode *q;       if(p->ltag==1)         return p->lchild;       else
       {
         q=p->lchild;         //从*p的左孩子开始查找         while(q->rtag==0)
           q=q->rchild;         return q;
       }
    }
登录后复制

   (3)遍历中序线索化二叉树的算法

void TraversInOrderThrTree(BiThrTree p)
    {      if(p)
      {        while(p->ltag==0)
          p=p->lchild;        while(p)
        {
          printf("%c",p->data);
          p=InOrderSuc(p);
        }
      }
    }
登录后复制

更多常见问题的相关技术文章,请访问常见问题栏目进行学习!

以上是二叉树的遍历算法的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

CLIP-BEVFormer:显式监督BEVFormer结构,提升长尾检测性能 CLIP-BEVFormer:显式监督BEVFormer结构,提升长尾检测性能 Mar 26, 2024 pm 12:41 PM

写在前面&笔者的个人理解目前,在整个自动驾驶系统当中,感知模块扮演了其中至关重要的角色,行驶在道路上的自动驾驶车辆只有通过感知模块获得到准确的感知结果后,才能让自动驾驶系统中的下游规控模块做出及时、正确的判断和行为决策。目前,具备自动驾驶功能的汽车中通常会配备包括环视相机传感器、激光雷达传感器以及毫米波雷达传感器在内的多种数据信息传感器来收集不同模态的信息,用于实现准确的感知任务。基于纯视觉的BEV感知算法因其较低的硬件成本和易于部署的特点,以及其输出结果能便捷地应用于各种下游任务,因此受到工业

使用C++实现机器学习算法:常见挑战及解决方案 使用C++实现机器学习算法:常见挑战及解决方案 Jun 03, 2024 pm 01:25 PM

C++中机器学习算法面临的常见挑战包括内存管理、多线程、性能优化和可维护性。解决方案包括使用智能指针、现代线程库、SIMD指令和第三方库,并遵循代码风格指南和使用自动化工具。实践案例展示了如何利用Eigen库实现线性回归算法,有效地管理内存和使用高性能矩阵操作。

探究C++sort函数的底层原理与算法选择 探究C++sort函数的底层原理与算法选择 Apr 02, 2024 pm 05:36 PM

C++sort函数底层采用归并排序,其复杂度为O(nlogn),并提供不同的排序算法选择,包括快速排序、堆排序和稳定排序。

人工智能可以预测犯罪吗?探索CrimeGPT的能力 人工智能可以预测犯罪吗?探索CrimeGPT的能力 Mar 22, 2024 pm 10:10 PM

人工智能(AI)与执法领域的融合为犯罪预防和侦查开辟了新的可能性。人工智能的预测能力被广泛应用于CrimeGPT(犯罪预测技术)等系统,用于预测犯罪活动。本文探讨了人工智能在犯罪预测领域的潜力、目前的应用情况、所面临的挑战以及相关技术可能带来的道德影响。人工智能和犯罪预测:基础知识CrimeGPT利用机器学习算法来分析大量数据集,识别可以预测犯罪可能发生的地点和时间的模式。这些数据集包括历史犯罪统计数据、人口统计信息、经济指标、天气模式等。通过识别人类分析师可能忽视的趋势,人工智能可以为执法机构

改进的检测算法:用于高分辨率光学遥感图像目标检测 改进的检测算法:用于高分辨率光学遥感图像目标检测 Jun 06, 2024 pm 12:33 PM

01前景概要目前,难以在检测效率和检测结果之间取得适当的平衡。我们就研究出了一种用于高分辨率光学遥感图像中目标检测的增强YOLOv5算法,利用多层特征金字塔、多检测头策略和混合注意力模块来提高光学遥感图像的目标检测网络的效果。根据SIMD数据集,新算法的mAP比YOLOv5好2.2%,比YOLOX好8.48%,在检测结果和速度之间实现了更好的平衡。02背景&动机随着远感技术的快速发展,高分辨率光学远感图像已被用于描述地球表面的许多物体,包括飞机、汽车、建筑物等。目标检测在远感图像的解释中

Java如何遍历文件夹并获取所有文件名 Java如何遍历文件夹并获取所有文件名 Mar 29, 2024 pm 01:24 PM

Java是一种流行的编程语言,具有强大的文件处理功能。在Java中,遍历文件夹并获取所有文件名是一种常见的操作,可以帮助我们快速定位和处理特定目录下的文件。本文将介绍如何在Java中实现遍历文件夹并获取所有文件名的方法,并提供具体的代码示例。1.使用递归方法遍历文件夹我们可以使用递归方法来遍历文件夹,递归方法是一种自身调用自身的方式,可以有效地遍历文件夹中

算法在 58 画像平台建设中的应用 算法在 58 画像平台建设中的应用 May 09, 2024 am 09:01 AM

一、58画像平台建设背景首先和大家分享下58画像平台的建设背景。1.传统的画像平台传统的思路已经不够,建设用户画像平台依赖数据仓库建模能力,整合多业务线数据,构建准确的用户画像;还需要数据挖掘,理解用户行为、兴趣和需求,提供算法侧的能力;最后,还需要具备数据平台能力,高效存储、查询和共享用户画像数据,提供画像服务。业务自建画像平台和中台类型画像平台主要区别在于,业务自建画像平台服务单条业务线,按需定制;中台平台服务多条业务线,建模复杂,提供更为通用的能力。2.58中台画像建设的背景58的用户画像

实时加SOTA一飞冲天!FastOcc:推理更快、部署友好Occ算法来啦! 实时加SOTA一飞冲天!FastOcc:推理更快、部署友好Occ算法来啦! Mar 14, 2024 pm 11:50 PM

写在前面&笔者的个人理解在自动驾驶系统当中,感知任务是整个自驾系统中至关重要的组成部分。感知任务的主要目标是使自动驾驶车辆能够理解和感知周围的环境元素,如行驶在路上的车辆、路旁的行人、行驶过程中遇到的障碍物、路上的交通标志等,从而帮助下游模块做出正确合理的决策和行为。在一辆具备自动驾驶功能的车辆中,通常会配备不同类型的信息采集传感器,如环视相机传感器、激光雷达传感器以及毫米波雷达传感器等等,从而确保自动驾驶车辆能够准确感知和理解周围环境要素,使自动驾驶车辆在自主行驶的过程中能够做出正确的决断。目