General idea
First of all, there are three kinds of tree traversal
- Preorder traversal The
order is the root node-left subtree-right subtree - Post-order traversal The
order is left subtree-right subtree-root node - In-order traversal The
order is left subtree-root node-right subtree
And for each node are executed recursively in the same order
Recursion
In the recursive mode, everyone is familiar with it, it is nothing more than the function body is called according to the order of traversal.
void preorder(TreeNode* root) {
if(root == nullptr) {
return;
}
ans.push_back(root ->val);
preorder(root -> left);
preorder(root -> right);
}
Modify the order in this format. If you want to know why this can be achieved, you can go through it yourself on the premise of knowing how to analyze the recursive process, which is the process of extension and backtracking. If you still don’t know how to analyze the recursive process, don’t memorize it and learn more about recursion.
Recursive implementation:
Preorder traversal
class Solution {
public:
vector<int> ans;
vector<int> preorderTraversal(TreeNode* root) {
if(root == nullptr) return {
};
preorder(root);
return ans;
}
void preorder(TreeNode* root) {
if(root == nullptr) {
return;
}
ans.push_back(root ->val);
preorder(root -> left);
preorder(root -> right);
}
};
In-order traversal
class Solution {
public:
vector<int> ans;
vector<int> inorderTraversal(TreeNode* root) {
if(root == nullptr) return {
};
inorder(root);
return ans;
}
void inorder(TreeNode* root) {
if(root == nullptr) {
return;
}
inorder(root -> left);
ans.push_back(root ->val);
inorder(root -> right);
}
};
Post-order traversal
class Solution {
public:
vector<int> ans;
vector<int> postorderTraversal(TreeNode* root) {
if(root == nullptr) return {
};
postorder(root);
return ans;
}
void postorder(TreeNode* root) {
if(root == nullptr) {
return;
}
postorder(root -> left);
postorder(root -> right);
ans.push_back(root ->val);
}
};
Non-recursive
The stack can be used to simulate recursive implementation. In fact, it reflects the idea of dfs. But the difficulty is much greater than recursion. The process must be analyzed and then expressed with the help of the stack. There is no obvious rule.
Preorder traversal
In the iterative algorithm, the idea evolved into a node A, it should be accessed immediately.
Because each subtree visits its root node first. For the left and right subtrees of a node, the root must also be visited first.
In the two subtrees of A, after traversing the left subtree, traverse the right subtree again.
Therefore, after visiting the root node, before traversing the left subtree, push the right subtree onto the stack.
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
if(root == nullptr) {
return {
};
}
stack<TreeNode*> s;
vector<int> ans;
s.push(root);
while(!s.empty()) {
TreeNode* tmp = s.top();
s.pop();
ans.push_back(tmp -> val);
if(tmp -> right) {
s.push(tmp -> right);
}
if(tmp -> left) {
s.push(tmp -> left);
}
}
return ans;
}
};
In-order traversal
At each node A, because the root access is in the middle, A is pushed onto the stack. Then traverse the left subtree, then visit A, and finally traverse the right subtree.
After accessing A, A can be popped from the stack. Because A and its left subtree have been visited.
See notes for specific ideas
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
if(root == nullptr) {
return {
};
}
stack<TreeNode*> s;
vector<int> ans;
TreeNode* cur = root;
//一开始cur不入栈防止入栈两次
while(cur || !s.empty()) {
while(cur) {
//将所有左子树入栈
s.push(cur);
cur = cur -> left;
}
//如果已经到了最左结点,将其入数组
cur = s.top();
s.pop();
ans.push_back(cur -> val);
//在根结点入数组的同时将根结点出栈,寻找根结点右边是否还有右子树
//如果发现就能继续递归的过程,
cur = cur -> right;
}
return ans;
}
};
Post-order traversal
Traversal sequence after sequence is about root **, and through the front left and right reversed order traversal subtree stack order , we can get root right-left sequence,
and then get the entire array can be reversed to get around the root . This is the best to understand, there is another solution that can refer to the solution of the big guy
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
if(root == nullptr) {
return {
};
}
stack<TreeNode*> s;
vector<int> ans;
s.push(root);
while(!s.empty()) {
TreeNode* tmp = s.top();
s.pop();
ans.push_back(tmp -> val);
if(tmp -> left) {
s.push(tmp -> left);
}
if(tmp -> right) {
s.push(tmp -> right);
}
}
reverse(ans.begin(), ans.end());
return ans;
}
};