先序遍历
vector<int> preorderTraversal(TreeNode* root, vector<int>& res;) { if (!root) return res; stack<TreeNode*> st; TreeNode* node = root; while (!st.empty() || node != nullptr) { while (node != nullptr) { res.push_back(node->val); st.push(node); node = node->left; } node = st.top(); st.pop(); node = node->right; } return res; }
中序遍历
vector<int> inorderTraversal(TreeNode* root, vector<int>& res) { if (!root) return res; stack<TreeNode*> st; TreeNode* node = root; while (!st.empty() || node != nullptr) { while (node != nullptr) { st.push(node); node = node->left; } node = st.top(); res.push_back(node->val); st.pop(); node = node->right; } return res; }
后序遍历
vector<int> postorderTraversal(TreeNode* root, vector<int>& res;) { if (!root) return res; stack<TreeNode*> st; TreeNode * cur; while (!st.empty() || root != nullptr) { while (root != nullptr) {; st.push(root); root = root->left; } root = st.top(); st.pop(); if (root->right == nullptr || root->right == cur) { res.push_back(root->val); cur = root; root = nullptr; } else { st.push(root); root = root->right; } } return res; }
从根节点开始遍历左子树,当前节点的左边元素也是它左子树的中间元素,遍历完左子树如果最后一个节点没有左右孩子也就是叶子结点,那么最后一个结点相当于是最后一棵左子树的左边元素,如果最后一个结点有右孩子,那么就相当于是最后一棵左子树的中间元素。
先序遍历遍历的顺序为中左右,先访问中间元素,要处理的也是中间元素,因此从根节点开始遍历左子树,将每个节点入栈,入栈的元素也就是中间元素和左边元素。每入栈一个元素就将它加入到结果数组res里,直到左子树为空,此时中间元素和左边元素都已经遍历完成,开始遍历右子树。
中序遍历遍历的顺序为左中右,先访问中间元素,要处理的是左边元素,因此处理过程与先序遍历略有不同。从根节点开始遍历左子树,将每个结点入栈直到左子树为空。此时栈里面的元素和先序遍历一样的,从栈底到栈顶是中左的顺序,那么从栈顶到栈底就是左中的顺序。此时栈顶元素就是左边元素,将其加入结果数组res里,此时栈顶元素出栈且访问其右子树,如果是叶子结点则没有右子树在将新的栈顶元素也就是中间的元素加入结果数组res里,此时在访问中间元素的右子树。
后序遍历遍历的顺序为左右中,此时与先序和中序都不太一样了。还是从根节点开始遍历左子树,将每个节点入栈,直到左子树为空,此时栈里的元素就是左中元素,如果是左边元素就加入结果数组res里。如果是中间元素且它的右孩子已经遍历过就将其加入结果数组res里,否则先将他入栈在访问他的右子树。