二叉樹前中後序遍歷非遞迴實現C

2021-09-27 13:12:00 字數 1839 閱讀 5977

前幾天面試過程中面試官讓手寫一下二叉樹後序遍歷的非遞迴寫法,當時沒有寫出來,本想著可能是因為面試太緊張的原因,才這麼簡單的題都沒寫出來,後來特地去研究了一下,發現二叉樹的後序遍歷非遞迴實現還真的沒我想的那麼簡單,在此寫個部落格記錄一下,順便把前序和中序的非遞迴實現也寫出來。

其實不管是前序、中序還是後序遍歷,都只需要使用乙個棧作為輔助來實現,其實現複雜度由到高分別為前序、中序、後序。下面按照前中後序遍歷的順序來記錄一下非遞迴實現的思路和**。

首先定義一下樹節點的結構體:

struct treenode

;

思路

前序遍歷的思路其實和dfs(深度優先搜尋)是一樣的,每次只需要從棧頂彈出乙個節點,並將該節點的孩子節點壓入棧,需要注意的就是,因為棧**先出的特性,要先壓右孩子再壓左孩子才能滿足前序遍歷的訪問順序。

//前序遍歷

void

preordervisit

(treenode* root)

}

思路

如果使用棧來實現中序遍歷,如果棧頂的當前節點沒有被訪問,那麼就需要不斷地把棧頂節點的左孩子壓入棧,反覆迴圈直到左孩子為空;那麼這樣就需要解決乙個問題:如何判斷棧頂的當前節點有沒有被訪問過呢?(即要判斷是第一次訪問還是經過回溯彈棧之後再次訪問);這裡的解決方法是用乙個bool型別的變數traceback來標記當前節點是否是通過回溯訪問的,traceback初始化為false,即標記為第一次訪問而不是回溯訪問。關鍵的是要在當前節點右孩子為空時,即回溯返回,將traceback置為true,當前棧頂的元素是回溯返回的再次方位,這樣就不會將其左孩子反覆壓入棧;如果右孩子不為空,將其右孩子壓入棧,並將traceback置為false,

//中序遍歷

void

inordervisit

(treenode* root)

else

traceback=true;

//若不存在右孩子,則標記為回溯返回

}}

思路

後序遍歷的實現思路和中序遍歷有相似的地方,都需要判斷當前棧頂節點是否是回溯返回,同樣的使用乙個bool型別的變數來標記是否是回溯返回。不一樣的地方就是父節點不能先於右孩子彈出棧,而是要繼續留在棧中,這就需要判斷當前節點(棧頂元素)的右孩子是否被訪問過(和之前判斷當前節點是否被訪問過不一樣,這裡是要判斷當前節點的右孩子是否被訪問過);對此可以使用乙個指標用來指向上一次出棧的節點,這樣在訪問當前節點的時候就可以判斷上一次出棧的節點是不是當前節點的右孩子;如果是它的右孩子則說明當前節點的右孩子已經被訪問過了,就不需要將右孩子壓棧了;否則需要將當前節點的右孩子壓入棧

//後序遍歷

void

postordervisit

(treenode* root)

else

if(nodestack.

top(

)->right!=nullptr)

}}

這裡自己構建一顆簡單的樹來驗證前面寫的前中後序遍歷的實現是否正確:

驗證**

int

main()

程式輸出

二叉樹前中後序遍歷非遞迴及應用

include include define m 50 typedef struct nodebtnode,btree void preorder btree t 前序非遞迴 p stack top p p rlink while p null top 1 void inorder btree t ...

二叉樹前中後序遍歷

前序遍歷a b d f g h i e c 中序遍歷f d h g i b e a c 後序遍歷f h i g d e b c a 前序 根左右 中序 左根右 後序 左右根 已知某二叉樹的前序遍歷為a b d f g h i e c,中序遍歷為f d h g i b e a c,請還原這顆二叉樹。思...

二叉樹前中後序遍歷

二叉樹 6.先序遍歷 10分 請編寫遞迴函式,實現二叉樹的先序遍歷。函式原型 先序遍歷 void bintreepreorder const tnode root 說明 root為二叉樹或子樹的根指標。在標頭檔案 bintree.h 新增函式宣告。bintree.h 先序遍歷 void bintre...