二叉树遍历的非递归算法

来源:互联网 发布:山东大学威海知乎 编辑:程序博客网 时间:2024/05/24 04:32

三种次序的寻访路线,它是从根结点开始沿左子树深入直到最左下端时,返回进入刚刚遇到结点的右子树;在右子树中,也是先深入到它的最左下结点时返回刚遇到结点的右子树······如此深入和返回,直到从根结点的右子树返回根结点止。在这一过程中,返回结点的顺序恰与深入结点的顺序相反,先深入的后返回,正好符合栈的特点。所以可以用栈来保存遍历过程中的结点信息来实现遍历二叉树的非递归算法,并且假定栈空间足够大不会发生栈上溢以简化算法。

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

思想:从二叉树的根结点开始,沿左子树一直深入到最左下结点时为止,在深入的过程中访问所遇到的结点,并把所遇到结点的非空右孩子进栈,当左子树结点全部处理完之后,从栈顶退出当前最近访问过结点的右孩子,再按上述过程遍历该结点的右子树;如此重复,直到栈空为止。

      在下面的算法中,二叉树以二叉链表存储,用一维数组stack[MAXSIZE]作为栈来保存结点的右孩子信息,top为栈顶指针,p始终指向寻访过程中当前要处理的结点。

[cpp] view plain copy
  1. #define MAXSIZE 100  
  2. void nrpreorder(bitree bt)//非递归前序遍历二叉树bt  
  3. {  
  4.     bitree stack[MAXSIZE],p;//定义局部变量  
  5.     int top=0;//栈指针初始化  
  6.     p=bt;//让p指向二叉树  
  7.     do  
  8.     {  
  9.         while(p!=NULL)//当p不为空时一直深入到最左下结点  
  10.         {  
  11.             printf("%d\n",p->data);//访问结点,假定data域为整型  
  12.             if(p->rchild!=NULL) //如果右子树不空  
  13.                 stack[++top]=p->rchild;//右孩子进栈  
  14.             p=p->lchild;//继续搜索p的左子树  
  15.         }  
  16.         if(top>0)  
  17.             p=stack[top--];//右孩子出栈赋p,准备搜索右子树  
  18.     }while(top>0);//当栈不空时继续遍历  
  19. }  

2.中序遍历二叉树的非递归算法思想:基本与前序遍历相同,只是沿左子树向下搜索的过程中先将所遇结点进栈,待遍历完左子树返回时从栈顶退出结点并访问,然后再遍历右子树。

[cpp] view plain copy
  1. #define MAXSIZE 100  
  2. void nrinorder(bitree bt)//非递归中序遍历二叉树bt  
  3. {  
  4.     bitree stack[MAXSIZE],p;//定义局部变量并初始化  
  5.     int top=0;  
  6.     p=bt;  
  7.     do  
  8.     {  
  9.         while(p!=NULL)//一直深入到最左下结点  
  10.         {  
  11.             stack[++top]=p;//所遇结点进栈  
  12.             p=p->lchild;//继续搜索p的左子树  
  13.         }  
  14.         if(top>0)  
  15.         {  
  16.             p=stack[top--];//出栈一个结点  
  17.             printf("%d\n",p->data);//访问结点  
  18.             p=p->rchild;//继续搜索右子树  
  19.         }  
  20.     }while(top>0);//当栈不空时继续遍历  
  21. }  

3.后序遍历二叉树的非递归算法

后序遍历二叉树的非递归算法要比前序和中序稍微复杂些。后序遍历中,当搜索指针指向一个结点时,不能马上访问,需要遍历先遍历左子树,所以结点需要进栈保存;当遍历完左子树返回再次搜索该结点时还不能进行访问,还需要遍历其右子树,所以结点需要再次进栈保存;即一个结点在两次进栈两次出栈之后才能访问。为了区别某一结点指针的两次出栈,需设置一标志flag同结点同时进出栈,flag定义如下:

flag={    0,  (结点第一次进出栈,不访问);

        {    1,  (结点第二次进出栈,出栈后访问);

栈中数据类型可定义为指向结点的指针和flag组成的结构体类型:

typedef struct stackelem

{

      bitree link;

      int flag;

}stackelemtype;

其后序遍历二叉树的非递归算法描述如下:

[cpp] view plain copy
  1. #define MAXSIZE 100  
  2. void nrpostorder(bitree bt)//非递归后序遍历二叉树bt  
  3. {  
  4.     stackelemtype stack[MAXSIZE];//定义栈  
  5.     bitree p;//定义巡访指针  
  6.     int top=0,sign;//栈顶指针初始化  
  7.     p=bt;//巡访指针指向二叉树的根结点  
  8.     do  
  9.     {  
  10.         if(p!=NULL)  
  11.         {  
  12.             stack[++top].link=p;//结点第一次进栈  
  13.             stack[top].flag=0;//置标志为0  
  14.             p=p->lchild;//遍历左子树准备  
  15.         }  
  16.         if(top>0)  
  17.         {  
  18.             sign=stack[top].flag;//标志出栈存于sign  
  19.             p=stack[top--].link;//结点出栈存于p  
  20.             if(sign==0)//flag为0,是第一次出栈  
  21.             {  
  22.                 stack[++top].link=p;//结点第二次入栈  
  23.                 stack[top].flag=1;//置标志为1  
  24.                 p=p->rchild;//遍历右子树准备  
  25.             }  
  26.             else//flag为1,是第二次出栈  
  27.             {  
  28.                 printf("%d\n",p->data);//访问结点  
  29.                 p=NULL;//置p为空,为下一个结点出栈做准备  
  30.             }  
  31.         }  
  32.     }while(top>0)  
  33. }  
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 衣服褶皱没有熨斗的情况下怎么办 裤子磨得发亮怎么办也没有电熨斗 老是在灯箱拍照对眼睛不好怎么办 电信光纤宽带账号密码忘记了怎么办 遇到尴尬的事情自己缓不过来怎么办 注销微信账号显示非法请求怎么办 微信备份以前的被覆盖了怎么办 之前微信号被新微信号覆盖了怎么办 微信发出的消息变成绿色怎么办 收了客户的资金被骗走了怎么办 淘宝退回去的衣服店家不接收怎么办 淘宝同款衣服价格相差很大该怎么办 淘宝买的衣服退回去了不退钱怎么办 淘宝客人退回的衣服有口红印怎么办 淘宝拍产品照片被投诉著作权怎么办 员工总在节假日忙的时候请假怎么办 买东西商家少给了货应该怎么办 买家退回的衣服有污渍卖家该怎么办 商家说衣服有污渍不退怎么办 退回商家换货不给寄应怎么办 毕业照跟拍摄影师拍砸了怎么办 韵达快递寄快递快递单号丢了怎么办 韵达快递把我的户口本弄丢了怎么办 淘宝卖家发货与实际货物不符怎么办 寄出去的快递不知道物流单号怎么办 淘宝买家所需要的货物填错怎么办 淘宝卖家顾客拒绝签收货要怎么办 闲鱼买家申请退货退款不发货怎么办 在闲鱼买东西买家恶意退货怎么办 淘宝卖家给的退货地址是国外怎么办 淘宝顾客下单了一件代发怎么办 闲鱼上卖东西快递单号填错了怎么办 淘宝收货后快递显示不签收怎么办 淘宝快递显示签收但没收到货怎么办 国外客人收到货后嫌弃质量差怎么办 理发15涨到20客人少了怎么办 微店买家收到货了又退款怎么办 百世快递单号查不到物流信息怎么办 知道快递单号怎么查物流信息怎么办 快递单号一直查不到物流信息怎么办 买家未收到货就发起仅退款怎么办