非再帰的なバイナリツリートラバーサル

大規模なデータ構造の約半数

知識ポイント

再帰的アルゴリズムは単純ですが、一般的には、その実装は非常に効率的ではありません。バイナリツリートラバーサルのための再帰アルゴリズムの実行時の動作は、非再帰的なアルゴリズムを得るために、スタックの作動状態の変化をモデル化することができます。
まず、非再帰的なアルゴリズム前順トラバーサル
非再帰的なアルゴリズムの前にキー前順は、バイナリツリーです:行きがけには、ノードの全体の左部分木を横断、ポインタは、図のための右のサブツリーのルートノードを見つける方法です。バイナリ
ここに画像を挿入説明
プロダクション・スタック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;            
                                 }        
                    }    
           }
}

後順の非再帰的なアルゴリズム
プルスタックノードは、スタック内の右部分木のノードを見つけることができないので、右のサブツリーまだトラバースするので、左のサブツリーを横断し、右のサブツリーをトラバースする準備ができている:とき右部分木、スタックスタックノードの上部、及びそれへのアクセスを横断した後。
スタックの取り扱い異なるノードを区別するために、フラグ変数フラグを設定し、フラグ= 1は左の部分木をトラバースさを示し、スタックノードをスタックすることはできません:フラグ= 2が横断右サブツリーを示し、ノードはスタックのトップであってもよいですスタックとアクセス。スタックの要素型は、構造C言語のタイプによって定義することができます。

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

BT用の二分木のルートポインタのセットを横断するように、次の2つの状況がある:
(1)それは、その左の部分木を横断するようにBTは、次いで、スタック上のフラグ、フラグ(1に設定)BT、NULLに等しくない場合。
BTはNULLに等しい場合、スタックはこの時点では空である(2)は、全体の反復が完了した:スタックが空でない場合、スタック・ノードの上部または左サブツリー右サブツリーが完了トラバースされます。フラグFLAG = 1つのスタックノード場合、それは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