二叉树遍历的非递归算法

大一下半期数据结构

知识点

递归算法虽然简单,但一般而言,其执行效率并不高。对于二叉树的遍历操作,可以仿照递归算法执行过程中工作栈的状态变化得到非递归算法。
一、前序遍历非递归算法
二叉树前序遍历非递归算法的关键是:在前序遍历过某结点的整个左子树后,如何找到该结点的右子树的根指针,对于图一二叉树
在这里插入图片描述
工作栈S和当前根指针bt的变化情况以及树中各结点的访问次序。
在这里插入图片描述

分析二叉树前序遍历的执行过程可以看出,在访问某结点后,应将该结点的指针保存在栈中,以便以后能通过它找到
该结点的右子树。一般情况下,在前序遍历中,设要遍历二叉树的根指针为bt,可能有两种情况:
(1)若bt!=NULL,则表明当前二叉树不为空,此时,应输出根结点bt的值并将bt保存到栈中,准备继续遍历bt的
左子树。
(2)若bt==NULL,则表明以bt为根指针的二叉树遍历完毕,并且bt是栈顶指针所指结点的左子树。若栈不为空,应根据栈顶指针所指结点找到待遍历右子树的根指针并赋予bt,以继续遍历下去:若栈为空,则表明整个二叉树遍历完毕,应结束。

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

void PreorderTraversal(  BiNode *root )//( BinTree BT )BinTree 为结构体指针,BiNode 为结构体类型
                                                          //二叉链表的根指针root
{
	BiNode *bt=root,*S[MaxSize];//定义顺序栈,工作指针bt初始化
	int top=-1;//初始化顺序栈
	while(bt!=NULL||top!=-1)//两个条件都不成立才退出循环
	{
		while(bt!=NULL)//当bt不空时循环
		{
			printf(" %c",bt->Data);//输出bt->data
			S[++top]=bt;//将指针bt保存到栈中
			bt=bt->lchild;//遍历bt的左子树
		}
		if(top!=-1)如果栈S不空,则
		{
			bt=S[top--];//将栈顶元素弹出至bt
			bt=bt->rchild;//准备遍历bt的右子树
		}
	
	}
}
void PreorderTraversal( BinTree BT )
{
    Stack s=CreateStack();
       //Push(s,BT);  
      BinTree now=BT;    
      if(now!=NULL)        
      Push(s,now);   
       while(!IsEmpty(s))
       {        now=Pop(s);        
                printf(" %c",now->Data);
                if(now->Right!=NULL)            
                Push(s,now->Right);
                if(now->Left!=NULL)     
                Push(s,now->Left);    
       }
}

中序遍历非递归算法
在中序遍历过程中遇到某结点不能立即访问它,而是将它压栈,等到它的左子树遍历完毕后,再从栈中弹出并访问之。

void InorderTraversal( BiNode *root  )//( BinTree BT )BinTree 为结构体指针,BiNode 为结构体类型
                                                          //二叉链表的根指针root
{
	BiNode *bt=root,*S[MaxSize];//定义顺序栈,工作指针bt初始化
	int top=-1;//初始化顺序栈
	while(bt!=NULL||top!=-1)//两个条件都不成立才退出循环
	{
		while(bt!=NULL)//当bt不空时循环
		{
			S[++top]=bt;//将指针bt保存到栈中
			bt=bt->lchild;//遍历bt的左子树
		}
		if(top!=-1)如果栈S不空,则
		{
			bt=S[top--];//将栈顶元素弹出至bt
			printf(" %c",bt->Data);//输出bt->data
			bt=bt->rchild;//准备遍历bt的右子树
		}
	
	}
}
void InorderTraversal( BinTree BT )
{        Stack s=CreateStack();
          if(BT!=NULL)      
          Push(s,BT);
          BinTree now; 
          while(!IsEmpty(s))
          {        while(Peek(s)->Left!=NULL)            
                   Push(s,Peek(s)->Left);        
                   while(!IsEmpty(s))
                   {            now=Peek(s);            
                                printf(" %c",now->Data);            
                                Pop(s);            
                                if(now->Right!=NULL)
                                {            Push(s,now->Right); 
                                              break;            
                                 }        
                    }    
           }
}

后序遍历非递归算法
当遍历完左子树,由于右子树尚未遍历,因此栈顶结点不能出栈,通过栈顶结点找到它的右子树,准备遍历它的右子树:当遍历完右子树,将栈顶结点出栈,并访问它。
为了区别对栈顶结点的不同处理,设置标志变量flag,flag=1表示遍历完左子树,栈顶结点不能出栈:flag=2表示遍历完右子树,栈顶结点可以出栈并访问。可以用c语言中的结构体类型来定义栈元素类型

typedef struct{
BiNode *ptr;
int flag;
}ElemType;//BiNode 为结构体类型

设要遍历二叉树的根指针为bt,则有以下两种情况:
(1)若bt不等于NULL,则bt及标志flag(置为1)入栈,遍历其左子树。
(2)若bt等于NULL,此时栈为空,则整个遍历结束:若栈不为空,则表明栈顶结点的左子树或右子树已遍历完毕。若栈顶结点的标志flag=1,则表明栈顶结点的左子树以遍历完毕,将flag改为2,并遍历栈顶结点的右子树:若栈顶结点的标志flag=2,则表明栈顶结点的右子树也遍历完毕,出栈并输出栈顶结点。

void PostorderTraversal(BiNode *root )
{
	ElemType S[MaxSize];//定义顺序栈
	int top=-1;初始化顺序栈
	BiNode *bt=root;//工作指针bt初始化
	while(bt!=NULL||top!=-1)//循环直到bt为空且栈S为空
	{
		while(bt!=NULL)
		{
			top++;
			S[top].ptr=bt;//root连同标志flag入栈
			S[top].flag=1;
			bt=bt->lchild;//继续遍历bt的左子树
		}
		while(top!=-1&&S[top].flag==2)//注意是循环,可能连续出栈
		//当栈S非空且栈顶元素的标志为2时,出栈并输出栈顶结点
		{
			bt=S[top--].ptr;
			printf(" %c",bt->Data);
		}
		if(top!=-1)//当栈非空,将栈顶元素的标志改为2,准备遍历栈顶结点的右子树
		{
			S[top].flag=2;
			bt=S[top].ptr->rchild;
		}
	}
 } 
void PostorderTraversal( BinTree BT )
{    Stack s=CreateStack();
    if(BT!=NULL)        
    Push(s,BT);    
    BinTree now=BT,last=NULL;
    while(!IsEmpty(s))
     {        while(Peek(s)->Left!=NULL)            
               Push(s,Peek(s)->Left);        
               while(!IsEmpty(s))
               {            now=Peek(s);            
                            if(now->Right==last||now->Right==NULL)
                            {               printf(" %c",now->Data);
                                            Pop(s);
                                           last=now;
                              }            
                              else
                              {                Push(s,now->Right);  
                                               break;            
                               }        
                }  
    }
}

添加链接描述
附大神博客地址

发布了46 篇原创文章 · 获赞 16 · 访问量 9455

猜你喜欢

转载自blog.csdn.net/weixin_43717681/article/details/89191772