leetcode 144.二叉树的前序遍历 94.二叉树的中序遍历 145.二叉树的后序遍历
想要正确无误地写出二叉树遍历的非递归算法,必须要明白系统栈调用存放节点的整个过程。
前序遍历
- 递归
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
void traversal(TreeNode* cur, vector<int>& vec) {
if (cur == NULL) return;
vec.push_back(cur->val); // 中
traversal(cur->left, vec); // 左
traversal(cur->right, vec); // 右
}
vector<int> preorderTraversal(TreeNode* root) {
vector<int> result;
traversal(root, result);
return result;
}
};
- 非递归1
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> s;
s.push(root);
while(!s.empty()){
TreeNode* p = s.top();
s.pop();
if(!p) continue;
res.push_back(p->val);
s.push(p->right);
s.push(p->left);
}
return res;
}
};
- 非递归2
- 基本思想:先访问根节点root及其所有左下节点,由于在二叉树中无法由孩子找到双亲,所以需要将这些访问过的节点进栈保存下来。此时当前栈顶节点要么没有左子树,要么左子树已经遍历过。
- 过程描述:首先p指向根节点,然后开始外循环,每一轮循环分为两个阶段,第一个阶段是沿着节点p的左下方向查找,边访问边进栈,直到没有左子树;第二个阶段出栈一个节点p,通过让p指向它的右孩子再重复循环来遍历右子树。
每一轮外循环结束时,所有栈中的节点均已访问且它的左子树已遍历,等待遍历右子树。
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> s;
TreeNode* p = root;
while(!s.empty()|| p){
while(p){ //访问节点p及其左下节点并进入栈
res.push_back(p->val); //访问操作
s.push(p); //节点p进栈
p = p->left; //移动到左孩子
}
if(!s.empty()){ //处理右孩子
p = s.top();
s.pop();
p = p->right;
}
}
return res;
}
};
- 过程如下:
中序遍历
- 递归
void traversal(TreeNode* cur, vector<int>& vec) {
if (cur == NULL) return;
traversal(cur->left, vec); // 左
vec.push_back(cur->val); // 中
traversal(cur->right, vec); // 右
}
- 非递归
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> s;
TreeNode* p = root;
while(!s.empty()|| p){
while(p){ //访问节点p及其左下节点并进入栈
s.push(p); //节点p进栈
p = p->left; //移动到左孩子
}
if(!s.empty()){ //处理右孩子
p = s.top();
res.push_back(p->val); //访问操作
s.pop();
p = p->right;
}
}
return res;
}
};
后序遍历
- 递归
void traversal(TreeNode* cur, vector<int>& vec) {
if (cur == NULL) return;
traversal(cur->left, vec); // 左
traversal(cur->right, vec); // 右
vec.push_back(cur->val); // 中
}
- 非递归
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
TreeNode *p, *r;
bool flag;
stack<TreeNode*> s;
vector<int> res;
p = root;
do{
while(p){
s.push(p);
p = p->left;
}
r = nullptr;
flag = true;
while(!s.empty()&&flag){
p = s.top();
if(p->right == r){
res.push_back(p->val);
s.pop();
r = p;
}else{
p = p->right;
flag = false;
}
}
}while(!s.empty());
return res;
}
};