打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
二叉树遍历算法总结

                                                                            二叉树遍历算法总结

    

   本文根据《数据结构与算法》(C语言版)(第三版) 整理。

   A.  二叉树的遍历

      1.前序遍历二叉树:

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

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

  1. void PreOrderTraverse(BiTree BT)  
  2. {  
  3.   if(BT)  
  4.   {  
  5.      printf("%c",BT->data);              //访问根结点  
  6.      PreOrderTraverse(BT->lchild);       //前序遍历左子树  
  7.      PreOrderTraverse(BT->rchild);       //前序遍历右子树  
  8.   }  
  9. }  

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

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

  1. void PreOrderNoRec(BiTree BT)  
  2. {  
  3.   stack S;  
  4.   BiTree p=BT->root;  
  5.   while((NULL!=p)||!StackEmpty(S))  
  6.   {  
  7.     if(NULL!=p)  
  8.     {  
  9.       printf("%c",p->data);  
  10.       Push(S,p);  
  11.       p=p->lchild;  
  12.     }  
  13.     else  
  14.     {  
  15.       p=Top(S);  
  16.       Pop(S);  
  17.       p=p->rchild;  
  18.     }  
  19.   }  
  20. }  

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

  1. void PreOrder(pBinTreeNode pbnode)  
  2. {  
  3.   pBinTreeNode stack[100];  
  4.   pBinTreeNode p;  
  5.   int top;  
  6.   top=0;  
  7.   p=pbnode;  
  8.   do  
  9.   {  
  10.     while(p!=NULL)  
  11.     {  
  12.       printf("%d\n",p->data);      //访问结点p  
  13.       top=top+1;  
  14.       stack[top]=p;  
  15.       p=p->llink;                  //继续搜索结点p的左子树  
  16.     }  
  17.     if(top!=0)  
  18.     {  
  19.       p=stack[top];  
  20.       top=top-1;  
  21.       p=p->rlink;                  //继续搜索结点p的右子树  
  22.     }  
  23.   }while((top!=0)||(p!=NULL));  
  24. }  

    2.中序遍历二叉树:

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

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

  1. void InOrderTraverse(BiTree BT)  
  2. {  
  3.   if(BT)  
  4.   {  
  5.      InOrderTraverse(BT->lchild);        //中序遍历左子树  
  6.      printf("%c",BT->data);              //访问根结点  
  7.      InOrderTraverse(BT->rchild);        //中序遍历右子树  
  8.   }  
  9. }  

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

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

  1. void IneOrderNoRec(BiTree BT)  
  2. {  
  3.   stack S;  
  4.   BiTree p=BT->root;  
  5.   while((NULL!=p)||!StackEmpty(S))  
  6.   {  
  7.     if(NULL!=p)  
  8.     {  
  9.       Push(S,p);  
  10.       p=p->lchild;  
  11.     }  
  12.     else  
  13.     {  
  14.       p=Top(S);  
  15.       Pop(S);  
  16.       printf("%c",p->data);  
  17.       p=p->rchild;  
  18.     }  
  19.   }  
  20. }  

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

  1. void InOrder(pBinTreeNode pbnode)  
  2. {  
  3.      pBinTreeNode stack[100];  
  4.      pBinTreeNode p;  
  5.      int top;  
  6.      top=0;  
  7.      p=pbnode;  
  8.      do  
  9.      {  
  10.        while(p!=NULL)  
  11.        {  
  12.          top=top+1;  
  13.          stack[top]=p;                //结点p进栈  
  14.          p=p->llink;                  //继续搜索结点p的左子树  
  15.        }  
  16.        if(top!=0)  
  17.        {  
  18.          p=stack[top];                //结点p出栈  
  19.          top=top-1;  
  20.          printf("%d\n",p->data);      //访问结点p  
  21.          p=p->rlink;                  //继续搜索结点p的右子树  
  22.        }  
  23.      }while((top!=0)||(p!=NULL));  
  24. }  
      

    3.后序遍历二叉树:

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

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

  1. void PostOrderTraverse(BiTree BT)  
  2. {  
  3.   if(BT)  
  4.   {  
  5.      PostOrderTraverse(BT->lchild);        //后序遍历左子树  
  6.      PostOrderTraverse(BT->rchild);        //后序遍历右子树  
  7.      printf("%c",BT->data);                //访问根结点  
  8.   }  
  9. }  

      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)遍历结束。
        使用栈的后序遍历非递归算法:
  1. void PostOrderNoRec(BiTree BT)  
  2. {  
  3.   stack S;  
  4.   stack tag;  
  5.   BiTree p=BT->root;  
  6.   while((NULL!=p)||!StackEmpty(S))  
  7.   {  
  8.     while(NULL!=p)  
  9.     {  
  10.       Push(S,p);  
  11.       Push(tag,0);  
  12.       p=p->lchild;  
  13.     }  
  14.     if(!StackEmpty(S))  
  15.     {  
  16.       if(Pop(tag)==1)  
  17.       {  
  18.         p=Top(S);  
  19.         Pop(S);  
  20.         printf("%c",p->data);  
  21.         Pop(tag);    //栈tag要与栈S同步  
  22.       }  
  23.       else  
  24.       {  
  25.         p=Top(S);  
  26.         if(!StackEmpty(S))  
  27.         {  
  28.           p=p->rchild;  
  29.           Pop(tag);  
  30.           Push(tag,1);  
  31.         }  
  32.       }  
  33.     }  
  34.   }  
  35. }  

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

  1. void PosOrder(pBinTreeNode pbnode)  
  2. {  
  3.      pBinTreeNode stack[100];       //结点的指针栈  
  4.      int count[100];                //记录结点进栈次数的数组  
  5.      pBinTreeNode p;  
  6.      int top;  
  7.      top=0;  
  8.      p=pbnode;  
  9.      do  
  10.      {  
  11.        while(p!=NULL)  
  12.        {  
  13.          top=top+1;  
  14.          stack[top]=p;                //结点p首次进栈  
  15.          count[top]=0;  
  16.          p=p->llink;                  //继续搜索结点p的左子树  
  17.        }  
  18.        p=stack[top];                  //结点p出栈  
  19.        top=top-1;  
  20.        if(count[top+1]==0)  
  21.        {  
  22.          top=top+1;  
  23.          stack[top]=p;                //结点p首次进栈  
  24.          count[top]=1;  
  25.          p=p->rlink;                  //继续搜索结点p的右子树  
  26.        }  
  27.        else  
  28.        {  
  29.          printf("%d\n",p->data);      //访问结点p  
  30.          p=NULL;  
  31.        }  
  32.      }while((top>0));  
  33. }  

     B 线索化二叉树:

       线索化二叉树的结点类型说明:
  1. typedef struct node  
  2. {  
  3.   DataType data;  
  4.   struct node *lchild, *rchild;       //左、右孩子指针  
  5.   int ltag, rtag;                     //左、右线索  
  6. }TBinTNode;         //结点类型  
  7. typedef TBinTNode *TBinTree;  
      在线索化二叉树中,一个结点是叶子结点的充分必要条件是其左、右标志均为1.

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

  1. void InOrderThreading(TBinTree p)  
  2.   
  3.  if(p)  
  4.  {  
  5.    InOrderThreading(p->lchild);   //左子树线索化  
  6.    if(p->lchild)  
  7.      p->ltag=0;  
  8.    else  
  9.      p->ltag=1;  
  10.    if(p->rchild)  
  11.      p->rtag=0;  
  12.    else  
  13.      p->rtag=1;  
  14.    if(*(pre))      //若*p的前驱*pre存在  
  15.    {  
  16.      if(pre->rtag==1)  
  17.        pre->rchild=p;  
  18.      if(p->ltag==1)  
  19.        p->lchild=pre;  
  20.    }  
  21.    pre=p;                         //另pre是下一访问结点的中序前驱  
  22.    InOrderThreading(p->rchild);   //右子树线索化  
  23.  }  
       

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

      ①结点p的右子树为空,那么p的右孩子指针域为右线索,直接指向结点p的后继结点。
      ②结点p的右子树不为空,那么根据中序遍历算法,p的后继必是其右子树中第1个遍历到的结点。
      
      中序线索化二叉树求后继结点的算法:
  1. TBinTNode *InOrderSuc(BiThrTree p)  
  2. {  
  3.    TBinTNode *q;  
  4.    if(p->rtag==1)   //第①情况  
  5.      return p->rchild;  
  6.    else            //第②情况  
  7.    {  
  8.      q=p->rchild;  
  9.      while(q->ltag==0)  
  10.        q=q->lchild;  
  11.      return q;  
  12.    }  
  13. }  
      
      中序线索化二叉树求前驱结点的算法:
  1. TBinTNode *InOrderPre(BiThrTree p)  
  2. {  
  3.    TBinTNode *q;  
  4.    if(p->ltag==1)  
  5.      return p->lchild;  
  6.    else  
  7.    {  
  8.      q=p->lchild;         //从*p的左孩子开始查找  
  9.      while(q->rtag==0)  
  10.        q=q->rchild;  
  11.      return q;  
  12.    }  
  13. }  

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

  1. void TraversInOrderThrTree(BiThrTree p)  
  2. {  
  3.   if(p)  
  4.   {  
  5.     while(p->ltag==0)  
  6.       p=p->lchild;  
  7.     while(p)  
  8.     {  
  9.       printf("%c",p->data);  
  10.       p=InOrderSuc(p);  
  11.     }  
  12.   }  
  13. }  

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
算法2(递归和非递归俩种方法实现二叉树的前序遍历)
第六章 树和二叉树
[树]基于二叉树的中序遍历非递归算法
数据结构_二叉树的遍历_课程设计
转:二叉树
二叉树的深度优先遍历、广度优先遍历和非递归遍历
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服