数据结构 二叉树的遍历
?? 所謂遍歷, 無非就是把1個容器的所有元素逐個輸出, 而這個輸出是線性的。
?? 但是二叉樹是1個非線性的容器,? 如何把它的元素按一定順序輸出就是1個值得學習的課題了。
?? 一般來講, 遍歷二叉樹有3種方法, 先序遍歷, 中序遍歷以及后續遍歷。 無論哪一種方法都可以把二叉樹里的元素線性輸出。但是無論哪種方法,都無法根據輸出后的線性元素還原成正確的二叉樹結構, 除非先把這棵二叉樹轉化為完全二叉樹(添加不存放實際數據的空節點)。
二叉樹先序遍歷的定義:
? ? ?? 定義很簡單, 無非3個步驟:
? ? ?? 第一步: 先訪問二叉樹的根節點
? ? ?? 第二步: 先序遍歷左子樹
? ? ?? 第三步 :? 先序遍歷右子樹 ??
? ? ?? 我們來看看上面先序遍歷的定義, 里面的步驟居然也用到了先序遍歷這個動作, 有經驗的讀者也許發現這就是遞歸了。
二叉樹先序遍歷的偽算法:
?????? 我們來假設先序遍歷這個函數是f(Tree * A);?? 其中A是二叉樹樹類型的指針?????? 那么f(Tree A)可以利用遞歸來定義:
?
f(Tree * A){printf(A->root); //root是Tree類型的一個成員,表示根節點if (NULL != A->LeftTree()){ //LeftTree 是Tree的一個成員,返回Tree的左子樹的指針(也是Tree類型指針) f(A->LeftTree());} if (NULL != A->RightTree()){ //RightTree 是Tree的一個成員,返回Tree的右子樹的指針(也是Tree類型指針)f(A->RightTree());} }????? 見到這個函數會不斷地調用自己, 直到左子樹和右子樹都為空(葉子節點), 才會遇到出口。
如下圖:
二叉樹中序遍歷的定義:
?????? 二叉樹的中序遍歷其實跟先序遍歷很類似, 都是利用遞歸來實現的, 但是中序遍歷執行步驟有些不同。
?????? 中序遍歷也分3個步驟:
?????? 第一步: 中序遍歷左子樹
? ? ?? 第二步: 訪問根節點
? ? ?? 第三步 :? 中序遍歷右子樹
??????
?????? 可以看出,跟先序遍歷的差別無非就是先遍歷左子樹和先訪問根節點的區別。
二叉樹中序遍歷的偽算法:
?????? 假設中序遍歷這個函數是g(Tree * A);?? 其中A是二叉樹樹類型的指針?????? 那么g(Tree A)可以利用遞歸來定義:
g(Tree * A){if (NULL != A->LeftTree()){ //LeftTree 是Tree的一個成員,返回Tree的左子樹的指針(也是Tree類型指針) g(A->LeftTree());} printf(A->root); //root是Tree類型的一個成員,表示根節點if (NULL != A->RightTree()){ //RightTree 是Tree的一個成員,返回Tree的右子樹的指針(也是Tree類型指針)g(A->RightTree());} }如下圖:
注意與先序遍歷的細節區別啊~
二叉樹后序遍歷的定義:
?????? 理解了先序和中序遍歷后, 后序遍歷也不難理解, 都是一個原理的啊。
?????? 后序遍歷的3個步驟:
?????? 第一步: 后序遍歷左子樹
? ? ?? 第二步: 后序遍歷右子樹
?????? 第三步 :? 訪問根節點
?????? 可以見到, 左子樹和右子樹的順序不變, 只不過根節點的順序留到最后了。
??????
二叉樹后序遍歷的偽算法:
?????? 假設后序遍歷這個函數是k(Tree * A);?? 其中A是二叉樹樹類型的指針?????? 那么k(Tree A)可以利用遞歸來定義:
k(Tree * A){if (NULL != A->LeftTree()){ //LeftTree 是Tree的一個成員,返回Tree的左子樹的指針(也是Tree類型指針) k(A->LeftTree());} if (NULL != A->RightTree()){ //RightTree 是Tree的一個成員,返回Tree的右子樹的指針(也是Tree類型指針)k(A->RightTree());}printf(A->root); //root是Tree類型的一個成員,表示根節點 }如下圖:
?????
? ? ??? ???
??
總結
以上是生活随笔為你收集整理的数据结构 二叉树的遍历的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据结构 非线性结构 树 介绍及存储方
- 下一篇: c语言位运算 求1个整数的二进制数有多少