資料結構-二叉樹遍歷
阿新 • • 發佈:2018-11-21
這篇博文主要是研究二叉樹遍歷的遞迴與非遞迴演算法,有興趣的小夥伴可以瞭解下!
二叉樹的遞迴遍歷(深度優先遍歷)
先來張圖,看看各結點遍歷時的情況:
二叉樹深度優先遍歷總結(分別為第一次,第二次,第三次進入某個結點):
- 先序遍歷:先訪問根結點,然後先序遍歷左子樹,最後先序遍歷右子樹;根->左->右
- 中序遍歷:先中序遍歷左子樹,然後訪問根結點,最後中序遍歷右子樹;左->根->右
- 後續遍歷:先後序遍歷左子樹,然後後序遍歷右子樹,最後訪問根結點;左->右->根
遞迴遍歷內部有系統棧,其作用:
- 1.保護現場(類似存檔)
- 2.恢復現場(類似讀檔)
遞迴遍歷程式碼比較簡單,先、中、後序遍歷遞迴程式碼基本相似,總程式碼:
void r(BTNode *p) { if (p != NULL) { //第一次進入-先序 r(p->lchild); //第二次進入-中序 r(p->rchild); //第三次進入-後序 } }
先序遍歷遞迴函式:
void r(BTNode *p) { if (p != NULL) { visit(p); r(p->lChild); r(p->rChild); } }
二叉樹的非遞迴遍歷(深度優先遍歷)
須知:需要自定製輔助棧
1.先序遍歷非遞迴:
1).利用輔助棧將根節點入棧,出棧操作,訪問該節點,將其右、左孩子分別入棧(每次訪問節點後,對其左、右孩子需要做一個檢測,為空的孩子無需入棧)
2).左孩子出棧,訪問該節點,將其右、左孩子分別入棧,多次操作!
3).直至棧空為止(出棧是在迴圈之內執行,即使棧空也會執行右左孩子入棧操作)
void preorderNonrecursion(BTNode *bt) { if (bt != NULL) //根節點是否為空 { BTNode *Stack[maxSize]; int top = -1; //建立棧 BTNode *p = NULL; //遍歷指標 Stack[++top] = bt; //節點入棧 while(top != -1) //棧不空時迴圈 { p = Stack[top--]; //出棧一個元素 Visit(p); //訪問 if(p->rChild != NULL) //右孩子不為空就入棧 Stack[++top] = p->rChild; if(p->lChild != NULL) //左孩子不為空就入棧 Stack[++top] = p->lChild; } } }
2.後序遍歷非遞迴:
// 先序(根左右),而後序(左右根),將後序逆轉為逆後序(根右左),逆後序的左右交換即可成為前序(根左右)
// 在這我們可以使用逆後序(根右左),把逆後序的結果壓入一個新棧,出棧就得到後序遍歷序列
1).將根節點入輔助棧(棧1),出棧操作,將出棧後的該元素入逆序棧(棧2),將其左、右孩子分別入輔助棧(每次對其左、右孩子需要做一個檢測,為空的孩子無需入棧);
2).右孩子出輔助棧(棧1),將出棧後的該元素入逆序棧(棧2),將其左、右孩子分別入輔助棧(棧1),多次操作;
3).直至輔助棧空為止,出棧是在迴圈之內執行,即使棧空也會執行左右孩子入棧操作;
4).逆序棧(棧2)中元素逐個出棧並訪問
void postorderNonrecursion(BTNode *bt) { if (bt != NULL) //根節點不為空 { BTNode *Stack1[maxSize];int top1= -1; //建立棧1(輔助遍歷的棧) BTNode *Stack2[maxSize];int top2= -1; //建立棧2(結果逆序的棧) BTNode *p = NULL; //遍歷指標 Stack1[++top1] = bt; //節點入棧1 while(top1 != -1) //棧不空時迴圈 { p = Stack1[top1--]; //棧1出棧一個元素 Stack2[++top2] = p; //出棧元素入棧2 if(p->lChild != NULL) //左孩子不為空就入棧 Stack[++top] = p->lChild; if(p->rChild != NULL) //右孩子不為空就入棧 Stack[++top] = p->rChild; } while(top2 != -1) { p = Stack2[top2--]; //棧2元素逐個出棧 Visit(p); //訪問 } } }
3.中序遍歷非遞迴程式碼
1).從根節點開始,一直左走,並把途徑的左孩子節點入棧;
2).遇到左孩子為空時,棧頂元素出棧,訪問該節點,p指向該節點的右孩子;
3).直到棧空或者P為NULL則遍歷結束
void inorderNonrecursion(BTNode *bt) { if(bt != NULL) //樹不空 { BTNode *Stack[maxSize];int top = -1; //建立棧 BTNode *p = NULL; //遍歷指標 p = bt; //節點入棧1 while(top1 != -1 || p != NULL) //棧不空或者p不空 { while(p != NULL) { Stack[++top] = p; //入棧 p = p->lChild; //左走 } if(top != -1) { p = Stack[top--]; //出棧 Visit(p); //訪問該節點 p = p->rChild; //右走 } } } }