二叉樹遍歷算法包含: 前序, 中序, 後序, 層次遍歷 共四種算法。算法
先序遍歷 DLR: 先訪問根節點,而後訪問左子樹, 最後訪問右子樹post
中序遍歷LDR: 先訪問左子樹,而後根節點,最後訪問右子樹遞歸
後序遍歷LRD: 先訪問左子樹,而後訪問右子樹,最後根節點隊列
層次遍歷: 從每層開始,至左向右逐層訪問it
先序、中序,後序均可以使用遞歸方式進行訪問,非遞歸方式使用棧輔助, 層次遍歷使用隊列做爲輔助結構二叉樹
1. 先序非遞歸遍歷算法:遍歷
每次遞歸深刻的時候,就是將左右孩子節點壓棧的過程,在壓棧以前,訪問該節點;top
每一個節點只有在訪問完右子樹,或者右子樹爲空時,出棧,爲了標誌每一個節點的右孩子節點是否壓棧,能夠使用一個標誌位flag,將節點的右孩子節點壓入棧中,須要改變flag,這樣每次訪問棧頂元素時,若是判斷右子樹已訪問,直接出棧;vi
詳細算法以下:while
最開始根節點入棧
while(棧非空){
1. 獲取棧頂元素cur;
2. 判斷該節點的flag, 若是flag爲true,說明該節點右子樹已經訪問,出棧, 不然 訪問該節點cur;
3. 若是cur有左孩子節點,壓入棧中,進入step 1;
不然,若是有右孩子節點(只有右子樹),壓入棧中,同時修改cur的標誌位flag爲true;若是cur爲葉子節點,直接出棧,進入step1
}
void preOrder(BitNode *t){
if(!t) return;
Stack<BitNode*> s;
s.push(t);
BitNode *cur=NULL;
while( !s.empty() ){
cur= s.top();
if(cur.flag){
//右子樹已經訪問,出棧
s.pop();
}else{
visit(cur); //訪問該節點
if(cur->lchild){
s.push(cur->lchild);//訪問左子樹
}else{
if(cur->rchild){//訪問右子樹
s.push(cur->rchild);
cur->flag= true;
}else{
//葉子節點
s.pop();
}
}
}
}
}
2. 中序遍歷非遞歸算法:
與先序遍歷相似,只是訪問完左子樹後訪問根節點,訪問完根節點,出棧,最後訪問完右子樹,爲了標誌每一個節點的左子樹是否訪問,使用標誌位flag
詳細算法以下:
最開始根節點入棧
while(棧非空){
1. 獲取棧頂元素cur;
2. 若是cur節點標誌位爲flag爲false, 且該節點有左子樹,將左子樹壓入棧中,同時置該節點標誌位flag爲true;不然訪問該節點,並出棧,若是該節點有右子樹,將右孩子壓入棧中
}
void inOrder(BitNode *t){
if(!t) return;
Stack<BitNode*> s;
s.push(t);
BitNode* cur=NULL;
while( !s.empty() ){
cur = s.top();
if(cur->flag){
visit(cur);
s.pop();
if(cur->rchild){
s.push(cur->rchild);
}
}
}//while
}
}
3. 後序遍歷二叉樹非遞歸算法:
先訪問左右子樹,最後訪問根節點,一樣的,若是該節點的左右子樹都已訪問,直接出棧,不然更新節點的訪問左右子樹狀態,若是狀態爲右子樹已經訪問,直接出棧
詳細算法以下:
最開始根節點入棧
while(棧非空){
1. 獲取棧頂元素cur;
2. 若是cur節點標誌位爲flag爲2, 右子樹已經訪問完,訪問該節點出棧, 不然,
若是flag==1, 代表該節點左子樹已經訪問,開始訪問右子樹,若是該節點無右子樹,訪問該節點後直接出棧 不然,將右孩子壓入棧中,同時置該節點標誌位flag爲2
若是flag==0,代表該節點左右子樹均未訪問, 先訪問左子樹,若是該節點有左子樹,將左子樹壓入棧中,同時置該節點標誌位flag爲1,代表左子樹已經訪問完, 不然判斷若是該節點有右子樹,將右孩子壓入棧中,同時置該節點標誌位flag爲2,不然該節點爲葉子節點,訪問該節點後直接出棧
}
void postOrder(BitNode *t){
if(!t) return;
Stack<BitNode*> s;
s.push(t);
BitNode* cur=NULL;
while( !s.empty() ){
cur = s.top();
if(cur->flag==2){
visit(cur);
s.pop();
}else if(cur-> flag==0 ){
if(cur->lchild){
s.push(cur->lchild);
cur->flag =1;
}else{
if(cur->rchild){
s.push(cur->rchild);
cur->flag=2;
}else{
//葉子節點
visit(cur);
s.pop();
}
}
}
}//while
}
4.層次遍歷算法:
使用隊列FIFO的特性,至左向右依次將根節點的孩子節點壓入隊列中