日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

二叉树的非递归遍历算法

發(fā)布時(shí)間:2023/12/20 编程问答 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 二叉树的非递归遍历算法 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

二叉樹的非遞歸及層次遍歷

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)如下:

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;//遍歷右孩子 }} }

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)如下:

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;//遍歷右孩子 }} }

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)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。