衆多周知,對於二叉樹的遍歷, 一種比較容易理解以及編寫的方式就是遞歸的方式了,下面針對二叉樹遍歷的中序遍歷作一個簡單的分析:算法
void travelTree(BiTree T, int deep){ if (T->lchild != NULL) travelTree(T->lchild, ++deep); for (int x = 0; x < deep; x++) { printf("--"); } printf("%c\n", T->data); if (T->rchild != NULL) travelTree(T->rchild, deep); }
俺們也知道,遞歸算法的思想有其值的咱們學習之處,可是,不過否定,遞歸的代價也是蠻高的,這得從遞歸的原理來分析,這裏作一下簡單的敘述:數據結構
你們都知道遞歸的實現是經過調用函數自己,函數調用的時候,每次調用時要作地址保存,參數傳遞等,這是經過一個遞歸工做棧實現的。具體是每次調用函數自己要保存的內容包括:局部變量、形參、調用函數地址、返回值。那麼,若是遞歸調用N次,就要分配N*局部變量、N*形參、N*調用函數地址、N*返回值。這勢必是影響效率的。函數
那麼,做爲遞歸的一種替代方式,棧的實現,就成爲了一種不錯的選擇:下面我就簡單的敘述一下,如何在實現二叉樹的遍歷中來運用棧的思想:學習
其實嘛,說到底,遞歸的底層(系統級)實現也是使用棧的,如上所說,故遞歸的棧替換依舊不足爲奇了,棧是一種先進後出結構的容器,經過簡單的數據結構(j結構體),咱們便可以模擬棧的實現,固然,本文主要是談二叉樹的遍歷,至於棧的實現嗎,讀者本身去查嗎!!!spa
一樣,咱們採用中序遍歷類舉例:指針
先敬上代碼:code
voidt InOrderTraverse(BiTree T, int(*Visit)(TElemType e)){ InitStake(S); Push(S, T); while (!StackEmpty(S)) { while (GetTop(S,P)&&p) Push(S, p->lchild); Pop(S, p); //空指針null退棧 有左孩子時,在沿着左孩子方向遍歷的時候,會把一個 //null push進棧沒左孩子的時候,上一次循環就一定會push進一個null 兩種狀況互斥 if (!StackEmpty(S)) { Pop(S, p); if (!Visit(p->data)) { return error; } Push(S, p->rchild); } } }
咱們一一個簡單的二叉樹爲例:blog
下面是棧操做過程:遞歸
其操做步驟能夠簡介爲以下:get
1:沿着p左孩子方向深度遍歷值沒有左孩子的節並按循序入棧。(前提:有左孩子) 最對會帶一個空指針
去棧頂的空指針(此時棧頂絕對有一個空指針)
2:操做棧頂節點節點(訪問)
3:p指向此節點的右節點(不詢問) 便可能爲空
重複。