二叉樹的遍歷方法之層序-先序-中序-后序遍歷的簡單講解和代碼示例


二叉樹的基礎性質及二叉樹的建立參見前面兩篇博文:
http://blog.csdn.net/why850901938/article/details/51052936
http://blog.csdn.net/why850901938/article/details/51052156

首先為了講解方便,我建立了如圖所示的二叉樹:
取名為:樹A

這里寫圖片描述

1.何為層序遍歷?
層序遍歷就是按照二叉樹的層次由上到下的進行遍歷,每一層要求訪問的順序為從左到右;
以樹A為例,層序遍歷得到的結果為:

5 2 6 1 4 8 3 7 9 11 10

2.何為先序遍歷?

先序遍歷的順序為先到根節點,再到左節點,最后到右節點;

我們來看樹A,首先從根節點5開始,先根輸出5,然后左子樹2,此時的位置在2,2相當於1和4兩個結點的根,所以遍歷2之后,先遍歷2的左子樹1,1沒有子結點,所以遍歷2的右子樹4,4有左子樹遍歷3,這樣完成了節點5的左子樹遍歷,再遍歷5的右子樹6,先遍歷6的左子樹,這里沒有,就遍歷6的右子樹8,然后再遍歷8的左右子樹,左子樹7,當然7沒有孩子結點,所以接下來是9,然后 11 10類似。
最后我們得到先序遍歷的結果為:

5 2 1 4 3 6 8 7 9 11 10

所以一定記住,訪問根結點的操作發生在遍歷其左右子樹之前,在樹A的例子中,訪問完5之后訪問2,接下來不是訪問6,而是訪問2的左右子樹。

3.何為中序遍歷?

中序遍歷就是先到左子樹、再到根節點、最后到右子樹;
這時我們建立樹B:
這里寫圖片描述

對樹B而言,中序遍歷就是 :

1 2 3

如果此時2節點有左右子樹,那么我們建立樹C:
這里寫圖片描述

此時對樹C而言,中序遍歷就是:
* 4 2 5 1 3 *

如果3節點有右子樹而沒有左子樹,我們建立樹D:
這里寫圖片描述

那么就是先訪問3節點再訪問6,結果為:

4 2 5 1 3 6

接下來回到我們的大家伙樹A;
對於樹A而言,其中序遍歷的結果為:

1 2 3 4 5 6 7 8 9 10 11

對於開始情況,在訪問5的時候,發現5有左子樹2,先2,再訪問2的時候發現有左子樹1,所以肯定還是A1先,所以這個序列是從1開始的。

是不是感到很神奇了!沒錯在中序遍歷中,根節點左邊所有數都在其左子樹上,右邊所有數都是在其右子樹上,這個性質有時解題會有用到;

4.何為后序遍歷?

對於后序遍歷而言,其訪問順序是先訪問左節點,再訪問右節點,最后才訪問根節點;

對於樹B:
后序遍歷得到的結果是:2 3 1

對於樹C:
后序遍歷得到的結果是:4 5 2 3 1

對與樹D:
后序遍歷得到的結果是:4 5 2 6 3 1

回到大家伙樹A:
其后序遍歷得到的結果應是:

1 3 4 2 7 10 11 9 8 6 5

所以也可以看出在后序遍歷中整顆數根節點是最后一個才遍歷到的;

接下來重頭戲到了,如何才能實現上述的四種遍歷呢?
我們首先從層序遍歷開始:

應當了解層序遍歷其實是一種典型的基礎BFS(寬度優先搜索)模型;
即以寬度為優先遍歷對象,從左到右的遍歷二叉樹,實現方法應當使用隊列
即如圖的平放管道模型,進出為單向通道:

這里寫圖片描述

隊列是一種特性為FIFO(first in first out)的數據結構模型,根據這種特性,從整棵樹的根節點開始,我們把每個根節點的左右節點依次壓進隊列中,根據先進先出特性,每次節點出來的順序就是完全和層序遍歷的順序相同。

我們以樹D為例進行講解:
從1節點開始,首先壓入1,對1進行壓入左右節點的操作依次壓入了2和3,
然后彈出1,接下來出來的是2,把2的左右節點4和5依次壓入,彈出2,接着壓入3,把的右節點6壓入,彈出3,至此第二層的搜索結束,進入第三層,則依次遍歷節點4 5 6 ,然后結束;

具體流程就是這樣,接下來是層序遍歷的代碼講解:

代碼如下:

void BFS(Node *Root)
{
queue<Node*> Q;//隊列的聲明
Node * node ;
Q.push(Root);//先壓入整棵樹的根節點Root
while(!Q.empty())//如果隊列不空則一直進行下去
{

node = Q.front();//訪問隊列的第一個元素
cout<<node->Value<<" ";//輸出當前節點的值
if (node->Left!=NULL)
{
Q.push(node->Left); //如果左節點不為空則壓入左節點
}
if (node->Right!=NULL)
{
Q.push(node->Right); //如果右節點不為空則壓入右節點
}
Q.pop(); //彈出當前節點
}
cout<<endl;
}

BFS代碼引自同學博客:http://blog.csdn.net/u011613367/article/details/50950408

關於隊列的基礎操作和其他數據結構及STL的知識歡迎訪問我的博文:
http://blog.csdn.net/why850901938/article/details/51052062

層序講完了,接下來我們講講先序,中序,后序遍歷的方法和代碼:
簡單來說先、中、后序遍歷都使用DFS(深度優先搜索)的方法,在我的理解中深搜所用的方法就是遞歸,也就是自己調用自己的。為何使用遞歸?
我們結合代碼進行講解:

首先是先序遍歷二叉樹:

void PreOrderTraverse(BiTree T)
{
if(T)//如果當前節點不為空
{
printf("%d ",T->data); //先輸出當前節點的值
PreOrderTraverse(T->Left); //再調用自己到左節點
PreOrderTraverse(T->Right);//最后到右節點
}
return;
}

然后中序遍歷:

void InOrderTraverse(BiTree T)
{
if(T)//如果當前節點不為空
{
PreOrderTraverse(T->Left); //先調用自己到左節點
printf("%d ",T->data); //再輸出當前節點的值
PreOrderTraverse(T->Right); //最后到右節點
}
}

最后后序遍歷:

void PostOrderTraverse(BiTree T)
{
if(T)//如果當前節點不為空
{
PreOrderTraverse(T->Left); //先調用自己到左節點
PreOrderTraverse(T->Right); //再到右節點
printf("%d ",T->data); //最后輸出當前節點的值

}
}

主函數如下:

int main()
{
BiTree T;
int d;
T = CreateBiTree(); //建立二叉樹
PreOrderTraverse(T); //先序遍歷
printf("\n");
InOrderTraverse(T); //中序遍歷
printf("\n");
PostOrderTraverse(T); //后序遍歷
printf("\n");
return 0;
}

建立二叉樹函數見:http://blog.csdn.net/why850901938/article/details/51052936

以上除注明引用處均為原創,圖片均為自己所制作,轉載請說明,給出鏈接就行~~~

僅代表個人觀點,歡迎交流探討,勿噴~~~

這里寫圖片描述

PhotoBy:WLOP

http://weibo.com/wlop


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com