144. 二叉树的前序遍历
145. 二叉树的后序遍历
94. 二叉树的中序遍历
二叉树的迭代遍历,也就是非递归遍历。思想就是利用栈存储节点,当访问的时候从栈弹出。
前序遍历
前序遍历的顺序是中左右,先将根节点的值放进数组中,再依次将右孩子、左孩子入栈,这样才能保证下次栈顶弹出的是上个节点的左孩子。
这里有两个操作:
- **处理:**将节点的数值放入数组中;
- **访问:**遍历节点。
注意:前序遍历的这两个操作顺序是先处理完后访问的。
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> result;
stack<TreeNode*> st;
if (root != nullptr)
st.push(root);
while (!st.empty()) {
TreeNode* node = st.top();
st.pop();
result.push_back(node->val);
if (node->right != nullptr)
st.push(node->right);
if (node->left != nullptr)
st.push(node->left);
}
return result;
}
};
中序遍历
中序遍历的顺序是左中右,跟前序遍历很大的不同是,那两步操作的顺序变为了访问、处理、再访问,也就会导致用上面相似的代码不能完成中序遍历。所以这里需要用一个指针来遍历节点,用栈来处理节点。
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
stack<TreeNode*> st;
TreeNode* cur = root;
while (cur != nullptr || !st.empty()) {
if (cur != nullptr) {
st.push(cur);
cur = cur->left;
} else {
cur = st.top();
st.pop();
result.push_back(cur->val);
cur = cur->right;
}
}
return result;
}
};
后序遍历
后序遍历的顺序是左右中,跟前序遍历很相似,两部操作的顺序是先访问后处理,所以再前序遍历的基础上稍稍改动就OK了。
先序遍历是中左右,改变代码的左右入栈顺序后就变为中右左,再reverse逆置一下就变为后序遍历的左右中了。
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> result;
stack<TreeNode*> st;
if (root != nullptr)
st.push(root);
while (!st.empty()) {
TreeNode* node = st.top();
st.pop();
result.push_back(node->val);
if (node->left != nullptr)
st.push(node->left);
if (node->right != nullptr)
st.push(node->right);
}
reverse(result.begin(), result.end());
return result;
}
};
这里补充前、中、后序的另外一种遍历方式
前序遍历
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> result;
stack<TreeNode*> st;
TreeNode* cur = root;
while (cur != nullptr || !st.empty()) {
while (cur != nullptr) {
result.push_back(cur->val);
st.push(cur);
cur = cur->left;
}
cur = st.top();
st.pop();
cur = cur->right;
}
return result;
}
};
中序遍历
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
stack<TreeNode*> st;
TreeNode* cur = root;
while (cur != nullptr || !st.empty()) {
while (cur != nullptr) {
st.push(cur);
cur = cur->left;
}
cur = st.top();
st.pop();
result.push_back(cur->val);
cur = cur->right;
}
return result;
}
};
后序遍历
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> result;
stack<TreeNode*> st;
TreeNode* cur = root;
while (cur != nullptr || !st.empty()) {
while (cur != nullptr) {
result.push_back(cur->val);
st.push(cur);
cur = cur->right;
}
cur = st.top();
st.pop();
cur = cur->left;
}
reverse(result.begin(), result.end());
return result;
}
};
以上的两种后序遍历都有一点不好,就是遍历的过程并不是后序,只是结果是后序遍历,所以这里给出另一种后序遍历方式。
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> result;
stack<TreeNode*> st;
TreeNode* cur = root;
TreeNode* prev = nullptr;
while (cur != nullptr || !st.empty()) {
while (cur != nullptr) {
st.push(cur);
cur = cur->left;
}
TreeNode* top = st.top();
if (top->right == nullptr || top->right == prev) {
result.push_back(top->val);
st.pop();
prev = top;
} else {
cur = top->right;
}
}
return result;
}
};