二叉樹中序遍歷、後序遍歷和層序遍歷非遞迴實現
阿新 • • 發佈:2018-11-21
一、中序遍歷
訪問順序:左子樹 -> 結點 -> 右子樹
難點在於訪問左子樹後應該怎麼回到結點本身或者其右子樹呢?這裡利用了堆疊來臨時儲存,需要利用上一個結點時可以pop出來(有種撤回鍵的感覺2333)。
void PreOrderTravel(BinTree BT){ BinTree T = BT; stack<BinTree> st; while(T || !st.empty()){ while(T){ st.push(T); T = T->left; } if(!st.empty()){ T = st.top(); st.pop(); printf("%d\n", T->data); T = T->right; } } }
P.S. 知道了中序遍歷的操作,先序遍歷就更簡單啦,只要在每次壓棧之前輸出結點資料就可以了。
二、後序遍歷
訪問順序:左子樹 -> 右子樹 -> 結點
Question:用這個結點訪問其左右子樹並且再回到其本身後,我怎麼判斷它先前有沒有訪問其左右子樹呢(是否輸出結點資料的判斷條件)?用臨時變數儲存已經輸出資料的結點node,如果當前結點的右子樹和node相等的話,則輸出;反之,不輸出。記得每次輸出後都要彈棧。
void PostOrderTravel(BinTree BT){ BinTree T = BT; stack<BinTree> st; while(T || !st.empty()){ while(T){ st.push(T); T = T->left; } if(!st.empty()){ T = st.top(); if( T->right && T->right != Temp){ T = T->right; }else{ printf("%d\n", T->data); Temp = T; T = NULL; //輸出過的資料不必再新增到堆裡,因此置NULL st.pop(); } } } }
一張圖看清先序、中序、後序之間的關係
三、層序遍歷
訪問順序:從上到下,從左到右
如上圖所示,將A結點pop出的時候,A的左右子樹(B、C)都進隊了;根據進隊順序,當B結點pop出的時候,B的左右子樹(D、F)進隊;以此類推。。。所以有了以下程式碼
void LevelOrderTravel(BinTree BT){ queue<BinTree> q; if(BT==NULL)return; q.push(BT); while(!q.empty()){ BT=q.front(); q.pop(); printf("%d\n", BT->Data); if(BT->left)q.push(BT->left); if(BT->right)q.push(BT->right); } }