二叉樹遍歷非遞迴寫法
阿新 • • 發佈:2019-02-14
來源:http://www.cnblogs.com/BaroC/p/5188545.html
遍歷的非遞迴實現是用棧來實現的,因為棧能提供先入後出。而對於層序遍歷,由於需要遵循層的順序,使用佇列。
1.先序遍歷(中左右)
初始化:根節點入棧。
迴圈:出棧一個節點,訪問這個節點,然後把這個節點的右子樹,左子樹入棧
(由於棧先入後出,所以最後的順序還是中-》左-》右)
Push(T,s);
while(!Empty(s)){
Tree temp = Pop(s);
visit(temp);
Push(temp->Right,s);
Push(temp->Left,s);
}
2.後序遍歷(左右中)
雙棧實現
初始化:根節點入棧
迴圈:出棧一個節點,把這個節點的右子樹入棧1,然後把這個節點的左子樹入棧1,把根節點放入棧2
放入棧2的順序是根-》右-》左
再訪問一次就是左右中了
完成迴圈以後,訪問順序在棧1中的順序是對的
迴圈2:訪問這個棧
<pre name="code" class="python">Push(T,S1) while(!Empty(S1)){ Tree temp = Pop(S1); Push(temp->Left,S1); Push(temp->Right,S1); Push(temp,S2); } while(!Empty(S2)){ Tree temp = Pop(S2); visite(temp); }
3.中序遍歷(左中右)
中序遍歷稍微複雜,使用一個指標p指向下一個待訪問的節點,p初始化為根節點。在每次迴圈中執行以下操作:
- 如果p非空,則把p入棧,p變為p的左兒子。
- 如果p為空,說明已經向左走到盡頭了,彈出當前棧頂元素,進行訪問,並把p更新為其右兒子。
也就是說,其實這種做法是先把根節點的所有左子節點全部入棧。這時候就要防止左子節點的重複訪問。
下面的程式碼是錯的,因為會形成迴圈訪問,
Push(T,S1) p = T; while(!Empty(S1)){ if(P->Left){ P=P->Left; Push(P,S1); } else{ visit(P); if(P->right){ P=P->right; Push(P,S1); } else{ P=Pop(S1); } } }
void inorder2(Node *root)//非遞迴中序遍歷
{
stack<Node *> stk;
Node *p = root;
while (p != NULL || !stk.empty())
{
if (p != NULL)
stk.push(p), p = p->left;
else
{
p = stk.top(); stk.pop();
printf("%d ", p->val);
p = p->right;
}
}
}
(上面的程式碼每次都做到了如果有左子節點,一定要訪問到底的要求)