C++實(shí)現(xiàn)二叉樹非遞歸遍歷算法詳解
一、二叉樹的前序遍歷
我們可以把任何一棵樹看成左路節(jié)點(diǎn),左路節(jié)點(diǎn)和右子樹。先訪問左路節(jié)點(diǎn),再訪問左路節(jié)點(diǎn)的右子樹。在右子樹中也重復(fù)這種循環(huán),就是非遞歸遍歷二叉樹的思想。

解釋:
棧st存放節(jié)點(diǎn),v存放數(shù)值,cur初始化為root。
循環(huán)條件是棧不為空或者cur不為空(訪問最后一個(gè)節(jié)點(diǎn)之前棧就已經(jīng)為空了),循環(huán)遍歷左子樹并且把左子樹入棧,同時(shí)把值存入v中。然后彈出棧頂元素,并且把棧頂元素的右子樹賦值給cur,這樣就形成了遍歷。
當(dāng)棧不為空的時(shí)候說明還有左路節(jié)點(diǎn)的右子樹沒有被訪問,當(dāng)cur不為空的時(shí)候說明還有樹要被訪問。當(dāng)同時(shí)為空的時(shí)候才是訪問完成。當(dāng)一個(gè)節(jié)點(diǎn)出棧的時(shí)候說明此時(shí)該節(jié)點(diǎn)及該節(jié)點(diǎn)的左子樹已經(jīng)被訪問完成了。
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
vector<int> v;
TreeNode* cur = root;
while(cur || !st.empty())
{
while(cur)
{
st.push(cur);
v.push_back(cur->val);
cur = cur->left;
}
TreeNode* node = st.top();
st.pop();
cur = node->right;// 轉(zhuǎn)化成子問題訪問右子樹
}
return v;
}
};
二、二叉樹的中序遍歷
因?yàn)橹行虮闅v的訪問順序是左根右,跟前序遍歷不同,所以我們讓左節(jié)點(diǎn)入棧的時(shí)候先不訪問,出棧(說明左子樹訪問完了)時(shí)在訪問節(jié)點(diǎn)。
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> v;
stack<TreeNode*> st;
TreeNode* cur = root;
while(!st.empty() || cur)
{
while(cur)
{
st.push(cur);
cur = cur->left;
}
TreeNode* node = st.top();
st.pop();
v.push_back(node->val);
cur = node->right;
}
return v;
}
};
三、二叉樹的后序遍歷
3.1 方法一
首先我們知道后序遍歷就是左右根,而我們可以把訪問順序變成根右左,然后再逆置順序。而根右左就跟前序遍歷的方法一樣:
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
vector<int> v;
TreeNode* cur = root;
while(cur || !st.empty())
{
while(cur)
{
st.push(cur);
v.push_back(cur->val);
cur = cur->right;
}
TreeNode* node = st.top();
st.pop();
cur = node->left;
}
reverse(v.begin(), v.end());
return v;
}
};
3.2 方法二
按照常規(guī)的遍歷方法走左右根,但是這里有一個(gè)問題:
當(dāng)訪問到根的時(shí)候有兩種情況:
1?? 從左子樹回來,現(xiàn)在要先訪問右子樹
2?? 從右子樹回來,左右子樹已經(jīng)訪問完畢,再訪問根。
針對(duì)這種情況我們可以在加一個(gè)變量來確定是第幾次訪問根,如果是第一次就訪問右子樹,如果是第二次就訪問。
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
stack<pair<TreeNode*, bool>> st;
vector<int> v;
TreeNode* cur = root;
while(cur || !st.empty())
{
while(cur)
{
st.push(make_pair(cur, false));
cur = cur->left;
}
TreeNode* node = st.top().first;
if(st.top().second == true)
{
st.pop();
v.push_back(node->val);
}
else
{
st.top().second = true;
cur = node->right;
}
}
return v;
}
};
到此這篇關(guān)于C++實(shí)現(xiàn)二叉樹非遞歸遍歷算法詳解的文章就介紹到這了,更多相關(guān)C++二叉樹非遞歸遍歷內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Cocos2d-x UI開發(fā)之CCControlButton控件類實(shí)例
這篇文章主要介紹了Cocos2d-x UI開發(fā)之CCControlButton控件類實(shí)例,本文代碼中包含大量注釋來講解CCControlButton控件類的使用,需要的朋友可以參考下2014-09-09
C/C++編譯報(bào)錯(cuò)printf was not declared in 
這篇文章主要介紹了C/C++編譯報(bào)錯(cuò)printf was not declared in this scope問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08
C++模擬實(shí)現(xiàn)string類的實(shí)例代碼
這篇文章主要給大家介紹了C++如何模擬實(shí)現(xiàn)string類,文章通過代碼示例講解的非常詳細(xì),有完整的實(shí)現(xiàn)過程,具有一定的參考價(jià)值,需要的朋友可以參考下2023-08-08
C++ 使用PrintWindow實(shí)現(xiàn)窗口截圖功能
這篇文章主要介紹了C++ 如何使用PrintWindow實(shí)現(xiàn)窗口截圖功能,文中示例代碼非常詳細(xì),幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下2020-08-08
C++返回值類型后置實(shí)現(xiàn)(跟蹤返回值類型)
本文主要介紹了C++返回值類型后置實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08

