来源: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;
}
}
}
(上面的代码每次都做到了如果有左子节点,一定要访问到底的要求)