稍微解釋一下:
先序遍歷。將根節點入棧,考察當前節點(即棧頂節點),先訪問當前節點,然後將其出棧(已經訪問過,不再需要保留),然後先將其右孩子入棧,再將其左孩子入棧(這個順序是為了讓左孩子位於右孩子上面,以便左孩子的訪問先於右孩子;當然如果某個孩子為空,就不用入棧了)。如果棧非空就重複上述過程直到棧空為止,結束演算法。
中序遍歷。將根節點入棧,考察當前節點(即棧頂節點),如果其左孩子未被訪問過(有標記),則將其左孩子入棧,否則訪問當前節點並將其出棧,再將右孩子入棧。如果棧非空就重複上述過程直到棧空為止,結束演算法。
後序遍歷。將根節點入棧,考察當前節點(即棧頂節點),如果其左孩子未被訪問過,則將其左孩子入棧,否則如果其右孩子未被訪問過,則將其右孩子入棧,如果都已經訪問過,則訪問其自身,並將其出棧。如果棧非空就重複上述過程直到棧空為止,結束演算法。
其實,這只不過是保證了先序中序後序三種遍歷的定義。對於先序,保證任意乙個節點先於其左右孩子被訪問,還要保證其左孩子先於右孩子被訪問。對於中序,保證任意乙個節點,其左孩子先於它被訪問,右孩子晚於它被訪問。對於後序,保證任意乙個節點的左孩子右孩子都先於它被訪問,其中左孩子先於右孩子被訪問。如是而已。
**裡應該體現得比較清楚。這裡不光給出了非遞迴版本,也給出了遞迴版本。
這裡需要強調一下:相對於教科書上實現方式,這種實現方式,visit和stack.pop總是結合在一起,這種非遞迴棧管理比較容易接受,而教科書上visit和pop可能是割裂的。最後會附上教科書上的實現方式。
void preordernorecursion(treeptr p)
} else
}
else if (stk.top().flag == 1)
}
else
if (!stackempty(s)) //通過下一次迴圈中的內嵌while實現右子樹遍歷
//endif
}//endwhile
}
2.中序遍歷非遞迴演算法
void inorderunrec(bitree *t)
if (!stackempty(s))
//endif
}//endwhile
}
3.後序遍歷非遞迴演算法
typedef enum tagtype;
typedef struct
stacknode;
typedef struct
sqstack;
void postorderunrec(bitree t)
while (!stackempty(s) && s.elem[s.top].tag==r)
if (!stackempty(s))
}while (!stackempty(s));
}//postorderunrec
我自己的實現:
#include #include using namespace std;
struct node
};void preorder(node* root)
if(tmp->l)
st.push(tmp->l);
}}void inorder(node* root)
else}}
}void postorder(node* root)
else
else}}
}
二叉樹非遞迴實現先序 中序 後序遍歷
測試資料 abc000de0f00g00 這是乙個先序序列 0表示當前結點為空 include includetypedef struct node node char chin 100 陣列從儲存獲取的二叉樹序列元素 int m int initchain node q,int step if q...
二叉樹先序 中序 後序 層序遍歷非遞迴實現
一 先序遍歷非遞迴實現 1.先建立乙個棧 2.把根節點放入棧中 3.迴圈取棧頂元素 4.訪問這個元素,並出棧 5.把當前元素的右子樹入棧 6.把當前元素的左子樹入棧 7.迴圈該過程 public static void preordernor treenode root 1.建立乙個棧 stacks...
二叉樹先序 中序 後序遍歷的非遞迴實現
在網上看了一些用非遞迴實現先序中序後序遍歷二叉樹的 都很混亂,while if各種組合巢狀使用,邏輯十分不清晰,把我也搞懵了。想了大半天,寫了大半天,突然開了竅,實際上二叉樹的這三種遍歷在邏輯上是十分清晰的,所以才可以用遞迴實現的那麼簡潔。既然邏輯如此清晰,那麼用非遞迴實現也應該是清晰的。自認為自己...