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