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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

前序-中序-后序-非递归-实现

發(fā)布時(shí)間:2024/4/14 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 前序-中序-后序-非递归-实现 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1. 簡述

??? 前序,根->左子樹->右子樹,中序,左子樹->根->右子樹,后序,左子樹->右子樹->根。
??? 本文主要關(guān)注三種遍歷方式的非遞歸實(shí)現(xiàn)。其中,中序和后序的實(shí)現(xiàn)來自參考中的“二叉樹的遍歷:前序,中序,后序,層序--包括遞歸和非遞歸實(shí)現(xiàn)”一文及其評論,前序比較簡單,單獨(dú)寫了個(gè)實(shí)現(xiàn)與參考的文中實(shí)現(xiàn)不同。另外,對于中序和后序,實(shí)現(xiàn)是一樣的,也沒什么意思,加了幾行注釋,就這樣了,實(shí)現(xiàn)主要是核心代碼,完整代碼在參考的文章中很詳細(xì)。
2. 前序非遞歸
????首先,棧頂元素入棧,然后進(jìn)入循環(huán),每次把棧頂元素輸出,元素出棧,將該元素的右孩子(如果存在)和左孩子(如果存在)依次入棧。?

void?PreOrder(Node*?root)?{ ? assert(NULL != root)
??stack
<Node*>?store;
??store.push(root);?
//?根結(jié)點(diǎn)入棧?
??while(!store.empty())?{?
????root
=?store.top(); //?在循環(huán)中,root記錄的是當(dāng)前準(zhǔn)備輸出的結(jié)點(diǎn)
????store.pop();
????cout?
<<?root->value?<<?"??";?//?輸出當(dāng)前結(jié)點(diǎn)?
????if(root->right_child)?//?右孩子入棧?
??????store.push(root->right_child);
????
if(root->left_child)?//?左孩子入棧?
??????store.push(root->left_child);?
??}
}

3. 中序非遞歸

????前序中的Root主要作為中間變量使用。這里的Root的意義是下一個(gè)要進(jìn)棧的結(jié)點(diǎn),初始值為根結(jié)點(diǎn)。
??? while (Root不為空 || 棧不為空) {
???????? if(Root不為空) // 一路向左入棧?
???????????? Root入棧
?????????????Root=Root->left_child。
??????? ?else?// 棧頂元素的左子樹都輸出過了
???????????? 輸出棧頂元素
???????????? Root=棧頂元素->right_child
???????????? 棧頂元素出棧。

??? }??

void?InOrder(Node*?root)?{
??assert(NULL?
!=?root);
??stack
<Node*>?store;
??
while(root?&&?!store.empty())?{
????
if(root?!=?NULL)?{?//?只要不為空,就一路向左結(jié)點(diǎn)方向走去?
??????store.push(root);
??????root?
=?root->left_child;
????}
????
else?{?//?store.top()的左邊都走過了?
??????cout?<<?store.top()->value?<<?"??";?//?輸出當(dāng)前結(jié)點(diǎn)?
??????root?=?store.top()->right_child;
??????store.pop();
????}
??}
}

4. 后序非遞歸

??? Root表示下一個(gè)要處理的結(jié)點(diǎn),初始化為根結(jié)點(diǎn),Per表示上一次剛剛輸出過的結(jié)點(diǎn)。
,Per的作用是對有孩子的結(jié)點(diǎn)進(jìn)行判斷,由于算法特性,每次到某個(gè)結(jié)點(diǎn)時(shí),其左子樹都輸出過了,此時(shí)只要判斷Pre是否是當(dāng)前結(jié)點(diǎn)的右孩子,如果不是,那么說明其右子樹沒走過,那么Root=當(dāng)前結(jié)點(diǎn)的右子樹,否則就是剛剛輸出了當(dāng)前結(jié)點(diǎn)的右孩子,由于是后序,其右子樹也必定都輸出過了,此時(shí)只要輸出當(dāng)前結(jié)點(diǎn),更新Pre就好了。
??? while(Root不為空?|| 棧不為空) {
???????? if(Root不為空)?// 一路向左
????????????Root入棧
??????????? Root=Root->left_child
???????? else {?//?此時(shí)棧頂元素的左子樹都輸出過了
???????????? Root =?棧頂元素
???????????? if(Root有右孩子 && Pre不等于Root的右孩子) // 此時(shí)棧頂元素的右子樹還沒輸出
???????????????? Root=Root->right
???????????? else //?此時(shí)棧頂元素的左右子樹都輸出過了
?????????????????輸出棧頂元素
?????????????????Pre = 棧頂元素
???????????????? 棧頂元素出棧?????????????????
??????????}

??? }

void?PostOrder(Node*?root)?{
??assert(NULL?
!=?root);
??Node
*?Pre?=?NULL;
??stack
<Node*>?store;
??
while(root?&&?!store.empty())?{
????
if(root?!=?NULL)?{?//?一路向左?
??????store.push(root);
??????root?
=?root->left_child;
????}
????
else?{?//?stack.top()的左子樹都輸出完了?
??????if(store.top()->right_child!=NULL?&&?store.top()->right_child!=Pre)?{?
??????
//?右子樹存在且沒有輸出過?
????????root?=?root->right_child;?
??????}?
??????
else?{?//?左右子樹都輸出過了?
????????cout?<<?store.top()->value?<<?"??";
????????Pre?
=?store.top();
????????store.pop();?
??????}?
????}
??}
}?

?

5. 參考

??? 二叉樹的遍歷:前序,中序,后序,層序--包括遞歸和非遞歸實(shí)現(xiàn)
??? http://www.cppblog.com/ngaut/archive/2006/01/01/2351.aspx

總結(jié)

以上是生活随笔為你收集整理的前序-中序-后序-非递归-实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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