前序-中序-后序-非递归-实现
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),每次把棧頂元素輸出,元素出棧,將該元素的右孩子(如果存在)和左孩子(如果存在)依次入棧。?
??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)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 给你的主机防火墙添加l7-filter
- 下一篇: TextSwitcher--文本切换器