二叉树的前中后序遍历之迭代法(统一风格迭代方式)
一、前序遍歷(迭代法)->右左中
前序遍歷是中左右,每次先處理的是中間節(jié)點(diǎn),那么先將根節(jié)點(diǎn)放入棧中,然后將右孩子加入棧,再加入左孩子。
為什么要先加入 右孩子,再加入左孩子呢?因?yàn)檫@樣出棧的時(shí)候才是中左右的順序。
注:前序遍歷要訪(fǎng)問(wèn)的元素和要處理的元素順序是一致的,都是中間節(jié)點(diǎn)
class Solution { public:vector<int> preorderTraversal(TreeNode* root) {vector<int> res;stack<TreeNode*> st;if(root!=nullptr) st.push(root);//將被訪(fǎng)問(wèn)的結(jié)點(diǎn)放入棧中while(!st.empty()) //此時(shí)棧內(nèi)不為空{TreeNode *node=st.top();//標(biāo)記棧頂元素(此時(shí)是被訪(fǎng)問(wèn)型元素)if(node!=nullptr)//若棧頂元素不為空{st.pop();//彈出棧頂元素if(node->right!=nullptr) st.push(node->right);//添加右結(jié)點(diǎn)(空節(jié)點(diǎn)不入棧)if(node->left!=nullptr) st.push(node->left);//添加左節(jié)點(diǎn)(空節(jié)點(diǎn)不入棧)st.push(node);//添加已被訪(fǎng)問(wèn)過(guò)的中間結(jié)點(diǎn)st.push(nullptr);//為此中間結(jié)點(diǎn)添加空標(biāo)記結(jié)點(diǎn)// if(node->left!=nullptr) st.push(node->left);//添加左節(jié)點(diǎn)(空節(jié)點(diǎn)不入棧)}else //當(dāng)被訪(fǎng)問(wèn)的結(jié)點(diǎn)為空節(jié)點(diǎn)的時(shí)候{st.pop();//彈出空節(jié)點(diǎn)node=st.top();//標(biāo)記將被處理的結(jié)點(diǎn)st.pop();res.push_back(node->val);//加入到結(jié)果集}}return res;} };二.中序遍歷(迭代法)->右中左
中序遍歷是左中右,先訪(fǎng)問(wèn)的是二叉樹(shù)頂部的節(jié)點(diǎn),然后一層一層向下訪(fǎng)問(wèn),直到到達(dá)樹(shù)左面的最底部,再開(kāi)始處理節(jié)點(diǎn)(也就是在把節(jié)點(diǎn)的數(shù)值放進(jìn)result數(shù)組中),這就造成了處理順序和訪(fǎng)問(wèn)順序是不一致的。無(wú)法使用棧。
那我們就將訪(fǎng)問(wèn)的節(jié)點(diǎn)放入棧中,把要處理的節(jié)點(diǎn)也放入棧中但是要做標(biāo)記。
如何標(biāo)記呢,「就是把正在訪(fǎng)問(wèn)的節(jié)點(diǎn)放入棧之后,彈出去,把它的右孩子加入棧,再把它自己加入,并且附帶一個(gè)空指針作為標(biāo)記,再把左孩子加入棧,此時(shí)棧頂元素就是將要被訪(fǎng)問(wèn)的結(jié)點(diǎn),再次重復(fù)以上步驟,直到全部結(jié)點(diǎn)都已入棧。」 這種方法也可以叫做標(biāo)記法
三、后序遍歷(迭代法)->中右左
class Solution { public:vector<int> postorderTraversal(TreeNode* root) {vector<int> res;stack<TreeNode*> st;if(root!=nullptr) st.push(root);//將被訪(fǎng)問(wèn)的結(jié)點(diǎn)放入棧中while(!st.empty()) //此時(shí)棧內(nèi)不為空{TreeNode *node=st.top();//標(biāo)記棧頂元素(此時(shí)是被訪(fǎng)問(wèn)型元素)if(node!=nullptr)//若棧頂元素不為空{st.pop();//彈出棧頂元素st.push(node);//添加已被訪(fǎng)問(wèn)過(guò)的中間結(jié)點(diǎn)st.push(nullptr);//為此中間結(jié)點(diǎn)添加空標(biāo)記結(jié)點(diǎn)if(node->right!=nullptr) st.push(node->right);//添加右結(jié)點(diǎn)(空節(jié)點(diǎn)不入棧)if(node->left!=nullptr) st.push(node->left);//添加左節(jié)點(diǎn)(空節(jié)點(diǎn)不入棧)}else //當(dāng)被訪(fǎng)問(wèn)的結(jié)點(diǎn)為空節(jié)點(diǎn)的時(shí)候{st.pop();//彈出空節(jié)點(diǎn)node=st.top();//標(biāo)記將被處理的結(jié)點(diǎn)st.pop();res.push_back(node->val);//加入到結(jié)果集}}return res;} };總結(jié)
只要理解3點(diǎn):以中序遍歷為例1.棧的特性入棧和出棧順序相反,想要輸出順序"左中右",入棧順序必須按照"右中左"。
2.入棧的處理:可以把整顆樹(shù)簡(jiǎn)化為3個(gè)節(jié)點(diǎn)一組的多個(gè)子樹(shù)。即(父節(jié)點(diǎn),左孩子,右孩子)這3個(gè)節(jié)點(diǎn)組成的子樹(shù)。每次循環(huán)處理的實(shí)際就是將這樣的3個(gè)節(jié)點(diǎn)按照規(guī)則順序(右中左)進(jìn)行入棧。所以才有了代碼中看到的:每次都是先將棧頂元素去除,然后對(duì)以棧頂元素做為父節(jié)點(diǎn)的3個(gè)節(jié)點(diǎn)子樹(shù)按規(guī)則順序(右中左)入棧。
3.NULL節(jié)點(diǎn)的加入和出棧規(guī)則的規(guī)定:保證了當(dāng)左孩子作為棧頂元素時(shí),不會(huì)立即出棧,而是會(huì)將當(dāng)前的左孩子(即棧頂元素)作為下次遍歷的父節(jié)點(diǎn)接著按照規(guī)則順序入棧。直到當(dāng)前的左孩子做為父節(jié)點(diǎn)再無(wú)孩子時(shí)(無(wú)孩子時(shí),入棧規(guī)則就成了(父節(jié)點(diǎn),NULL節(jié)點(diǎn))),遇到NULL節(jié)點(diǎn)了,才進(jìn)行出棧。這樣就保證了左孩子先出棧啦
總結(jié)
以上是生活随笔為你收集整理的二叉树的前中后序遍历之迭代法(统一风格迭代方式)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 二叉树的前中后序遍历之迭代法(非统一风格
- 下一篇: 立个flag,一个月之内把知识点整理完,