【數據結構】二叉樹的遍歷方式:前中後序遍歷(遞歸與非遞歸堆棧方法實現)、層序遍歷

       二叉樹的遍歷方式有很多種:前序遍歷、中序遍歷、後序遍歷以及層序遍歷等,遍歷也可分遞歸與非遞歸方式,下面將用以下這顆二叉樹進行各個遍歷方式的講解:

                                                                    

                           文          

一.先序遍歷(遞歸方式)

     先序遍歷的遍歷順序爲:

     按照此順序對上述二叉樹進行遍歷的步驟爲:

     先訪問主結點:

                                                                  

       再訪問左結點: 
                                                                      

      理論上是要訪問該結點的左結點,但是該結點的左結點不存在,所以訪問其右節點:

                                                                  

       後來,訪問該結點的左結點,沒有,再訪問右結點,也沒有,所以以“1”爲主結點的左邊遍歷結束,開始遍歷右邊結點:

                                                                      

        訪問左結點:

                                                                      

    然後訪問其左結點,沒有,所以訪問其右結點:

                                                                

     最後訪問結點“3”的右結點,沒有,結束遍歷,所以前序遍歷最後輸出:

                                                        

     代碼使用遞歸的方式進行遍歷,代碼量少,但是佔用空間資源大:

void Preorder(Node* n)
{
	if (n)
	{
		printf("%d ", n->data);
		Preorder(n->left);
		Preorder(n->right);
	}
}

 

二.中序遍歷(遞歸)

     中序遍歷的遍歷順序爲:

     按照此順序對上述二叉樹進行遍歷的步驟爲:

     先訪問左結點:

                                                  

       再訪問結點 “2” 的左結點,但是沒有,所以左邊遍歷結束,輸出中結點 “2” ,再訪問右結點,輸出“5”:

                                                  

       然後主結點 “1” 的左節點遍歷完成,訪問中結點,也就是自己,輸出 “1” :

                                                        

        開始訪問 “1” 的右結點 “3” :

                                                         

     左結點存在,所以訪問其左結點:

                                                                  

      再訪問 “6” 的左結點,但是不存在,所以訪問中結點,也就是自己,輸出“6”,訪問右結點:

                                                           

    身爲右結點的“13” 即沒有左結點也沒有右結點,所以輸出自己,跳回到 “3” :

                                                                

    理論上訪問完“3”的左結點後開始訪問其右結點的,但是不存在,所以輸出自己 “3” ,最後得出中序遍歷的結果:                       

                                                   

   代碼如下(遞歸方法):

void Middle_order(Node* n)
{
     if (n)
    {
	Middle_order(n->left);

	printf("%d ", n->data);

	Middle_order(n->right);
    }
}

 

三.後序遍歷 (遞歸)

     後序遍歷的遍歷順序爲:

     按照此順序對上述二叉樹進行遍歷的步驟爲:

     先訪問左結點:

                                                      

    再訪問“2”的左結點,沒有,所以訪問右結點“5”:

                                            

 

    訪問“5”的左右結點,沒有,所以輸出自己,箭頭指回“2”:

                                                   

    至此“1”的左邊結點遍歷完成,開始遍歷右邊結點,箭頭指向“3”:

                                                  

       訪問其左結點“6”:

                                                     

      隨後再訪問“6”的左結點,沒有,所以訪問其右結點“13”:

                                                          

     “13”沒有左右結點,所以輸出自己,箭頭指回“6”:

                                                           

       輸出“6”,箭頭指回“3”,輸出“3”,主結點“1”的右結點也遍歷完成,最後輸出中結點,也就是自己“1”:

                                                             

      最後得出中序遍歷的結果:

                                             

     代碼如下(遞歸方法):

void Post_order(Node* n)
{
	if (n)
	{
		Post_order(n->left);
		Post_order(n->right);
		printf("%d ", n->data);
	}
}

四.前中後序非遞歸堆棧方法

       使用堆棧的方法可以避免遞歸過程中遇到的空間資源浪費的問題,前中後序的堆棧方法都相類似,所以下面以中序遍歷爲例子進行講解,堆棧的核心思想是遍歷的結點存在,則壓入棧中,不存在,則將棧中數據壓出,第一步是先創建一個空棧:

                                                        

      按照先序遍歷的順序是,所以先將主結點 “1” 壓入棧中:

                                                         

      隨後訪問其左結點 “2”,將其壓入棧中:

                                                             

     再訪問“2” 的左結點,沒有,所以從棧中壓出一個數據“2”:

                                                

      隨後訪問右結點“5”,存在,所以將其壓入棧中:

                                                      

    隨後訪問“5”的左結點,不存在,所以從棧中壓出一個數據:

                                                          

    再訪問“5” 的右結點,沒有,所以再次從棧中壓出一個數據:

                                                          

     至此結點“1” 的左結點遍歷完成,開始遍歷其右結點“3”,壓入棧中:

                                                          

      然後訪問其左結點“6”,壓入棧中:

                                                            

     再訪問其左結點,不存在,所以壓出棧中一個數據:

                                                          

     訪問其右結點“13”,壓入棧中:

                                                      

     訪問“13”的左結點,不存在,從棧中壓出一個數據:

                                                            

      最後訪問“13”的右結點,不存在,所以壓出棧中的數據:

                               

       最後輸出中序遍歷後的結果:

                                           

       中序遍歷代碼如下:

void Stack_Middle_order(Node* n)
{
	Node* N = n; //創建二叉樹
	Stack S = CreateStack(100); //創建棧
	while (N || !IsEmpty(S))
	{
		while (N)
		{
			Push(S, N); //壓棧
			N = N->left;
		}
		if (!IsEmpty(S)) //判斷棧堆是否爲空
		{
			N = Pop(S); //出棧                
			printf("%d ", N->data);
			N = N->right;
		}
	}
}

五.層序遍歷

       層序遍歷最簡單,就是從上往下進行遍歷,如以下二叉樹:

                                                 

      使用層序遍歷就可以按照順序進行輸出:1,2,3,5,6,13,代碼思路可以選擇使用隊列+遞歸來實現,根據隊列的“先進後出”的特性可以滿足層序遍歷的需求。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章