二叉树的非递归遍历算法
二叉樹的非遞歸及層次遍歷
1.前序遍歷
遍歷順序:根節點→左孩子→右孩子;
具體算法思想:將二叉樹的根結點賦值給遍歷的指針,由該指針進行遍歷;若當前節點非空,則訪問該節點并將該節點壓棧(將該節點的地址壓棧),繼而遍歷其左子樹;循環執行,直到當前節點為空時,取棧頂元素并訪問其右子樹,再重復如上操作,直至遍歷節點的指針為空且棧也為空;
具體遍歷過程如圖:
算法代碼實現如下:
2.中序遍歷
遍歷順序:左孩子→根節點→右孩子;
具體算法思想:將二叉樹的根結點賦值給遍歷的指針,由該指針進行遍歷;若當前節點非空,則將該節點壓棧并訪問其左子樹,循環執行,直至當前節點為空時,取棧頂元素訪問并彈棧,然后訪問其右子樹,再重復如上操作,直至遍歷節點的指針為空在且棧也為空。(中序遍歷和前序遍歷的不同在于:前序遍歷是入棧的同時訪問結點,而中序遍歷是出棧的同時訪問結點);
具體遍歷過程如圖:
算法代碼實現如下:
3.后序遍歷
遍歷順序:左孩子→右孩子→根節點;
具體算法思想:將二叉樹的根結點賦值給遍歷的指針,由該指針進行遍歷;若當前節點非空,則將該節點壓棧并訪問其左子樹,循環執行,直至當前節點為空時,取棧頂元素,判斷其右子樹是否為空且是否已遍歷,如果非空且為遍歷則訪問其右子樹,再將其壓棧遍歷其左子樹;如果右子樹為空或已遍歷則訪問該結點并彈棧,同時設置標記指針記錄遍歷過的點(用于判斷右子樹是否已遍歷),再將遍歷指針置空(下次遍歷直接取棧頂元素),直至遍歷節點的指針為空且棧也為空。
算法代碼實現如下:
void postorder(BiTree T){ //二叉樹的非遞歸后序遍歷 BiTree r=NULL;stack<BiTree> s;while(T||!s.empty()){if(T!=NULL){//當結點不為空時,該結點壓棧并遍歷其左子樹 s.push(T);T=T->lchild;}else{//當左子樹結點為空時,取棧頂元素進行右子樹的遍歷, T=s.top();if(T->rchild!=NULL&&T->rchild!=r){//右子樹不為空且右子樹沒有被遍歷過 T=T->rchild;s.push(T);//將該結點壓棧,遍歷其左子樹 T=T->lchild;}else{//右子樹為空或已遍歷則取棧頂元素訪問該結點的信息 s.pop();cout<<T->data;r=T;//標記遍歷過的點,用于判斷右子樹是否已遍歷 T=NULL;//遍歷結點的指針置空,下次遍歷直接取棧中的值 }}} }4.層次遍歷
具體算法思想:將根節點入隊,訪問隊頭元素,并將其左右孩子入隊,循環直至隊列為空結束。
算法代碼實現如下:
void leveorder(BiTree T){ //層次遍歷 deque<BiTree> d;if(T)//根結點不為空時入隊 d.push_back(T); while(!d.empty()){//當隊不為空時循環 T=d.front();//取隊頭元素并訪問該點信息 cout<<T->data;if(T->lchild)//將該結點的左孩子和右孩子納入隊中 d.push_back(T->lchild);if(T->rchild)d.push_back(T->rchild);d.pop_front();//隊頭元素出隊} }5.具體實現
#include <bits/stdc++.h> #define INIT ios::sync_with_stdio(false) using namespace std; typedef struct BiTNode{int data;struct BiTNode *lchild,*rchild; }BiNode,*BiTree; void creat(BiTree &T){int n;cin>>n;if(n==0)//輸入0時表示結點為空 T=NULL;else{T=new BiNode;T->data=n;creat(T->lchild);//創建左子樹 creat(T->rchild);//創建右子樹 } } void preorder(BiTree T){ //二叉樹的非遞歸前序遍歷 stack<BiTree> s;while(T||!s.empty()){//當前結點或棧不為空時執行該循環 if(T!=NULL){//當前結點不為空時 cout<<T->data;//訪問當前結點信息 s.push(T);//將該節點的地址壓棧 T=T->lchild;//遍歷左孩子 }else{//當前結點為空時 T=s.top();//取棧頂的元素 s.pop();//彈棧 T=T->rchild;//遍歷右孩子 }} } void inorder(BiTree T){ //二叉樹的非遞歸中序遍歷 stack<BiTree> s;while(T||!s.empty()){//當前結點或棧不為空時執行該循環 if(T!=NULL){//當前結點不為空時s.push(T);//將該節點的地址壓棧T=T->lchild;//遍歷左孩子}else{T=s.top();//取棧頂的元素s.pop();//彈棧cout<<T->data;//訪問當前結點信息T=T->rchild;//遍歷右孩子 }} } void postorder(BiTree T){ //二叉樹的非遞歸后序遍歷 BiTree r=NULL;stack<BiTree> s;while(T||!s.empty()){if(T!=NULL){//當結點不為空時,該結點壓棧并遍歷其左子樹 s.push(T);T=T->lchild;}else{//當左子樹結點為空時,取棧頂元素進行右子樹的遍歷, T=s.top();if(T->rchild!=NULL&&T->rchild!=r){//右子樹部位空且右子樹沒有被遍歷過 T=T->rchild;s.push(T);//將該結點壓棧,遍歷其左子樹 T=T->lchild;}else{//右子樹為空或已遍歷則取棧頂元素訪問該結點的信息 s.pop();cout<<T->data;r=T;//標記遍歷過的點,用于判斷右子樹是否已遍歷 T=NULL;//遍歷結點的指針置空,下次遍歷直接取棧中的值 }}} } void leveorder(BiTree T){ //層次遍歷 deque<BiTree> d;if(T)//根結點不為空時入隊 d.push_back(T); while(!d.empty()){//當隊不為空時循環 T=d.front();//取隊頭元素并訪問該點信息 cout<<T->data;if(T->lchild)//將該結點的左孩子和右孩子納入隊中 d.push_back(T->lchild);if(T->rchild)d.push_back(T->rchild);d.pop_front();//隊頭元素出隊} } int main() {INIT;BiTree T;creat(T);preorder(T);//先序 cout<<endl;inorder(T);//中序 cout<<endl;postorder(T);//后序 cout<<endl;leveorder(T);//層次 cout<<endl;return 0; }總結
以上是生活随笔為你收集整理的二叉树的非递归遍历算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 你知道kernel version的实现
- 下一篇: 深入理解cache对写好代码至关重要