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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

二叉树的非递归遍历算法

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

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

1.前序遍歷

遍歷順序:根節點→左孩子→右孩子

具體算法思想:將二叉樹的根結點賦值給遍歷的指針,由該指針進行遍歷;若當前節點非空,則訪問該節點并將該節點壓棧(將該節點的地址壓棧),繼而遍歷其左子樹;循環執行,直到當前節點為空時,取棧頂元素并訪問其右子樹,再重復如上操作,直至遍歷節點的指針為空且棧也為空;

具體遍歷過程如圖:

算法代碼實現如下:

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

2.中序遍歷

遍歷順序:左孩子→根節點→右孩子

具體算法思想:將二叉樹的根結點賦值給遍歷的指針,由該指針進行遍歷;若當前節點非空,則將該節點壓棧并訪問其左子樹,循環執行,直至當前節點為空時,取棧頂元素訪問并彈棧,然后訪問其右子樹,再重復如上操作,直至遍歷節點的指針為空在且棧也為空。(中序遍歷和前序遍歷的不同在于:前序遍歷是入棧的同時訪問結點,而中序遍歷是出棧的同時訪問結點);

具體遍歷過程如圖:

算法代碼實現如下:

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

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; }

總結

以上是生活随笔為你收集整理的二叉树的非递归遍历算法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。