递归遍历二叉树
题目链接:二叉树的前序遍历 二叉树的后序遍历 二叉树的中序遍历
视频讲解:每次递归都要靠直觉?
总结递归三要素,每次递归都要按照三要素来写
1、确定递归函数的参数和返回值:确定哪些参数是递归的过程中需要处理的,那么就在递归的函数里加上这个参数,并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。
2、确定终止条件:写完了递归算法,运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果没有终止,操作系统的内存栈必然就会溢出。
3、确定单层递归的逻辑:确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。
学会自己定义一个二叉树
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
前序遍历
class Solution {
public:
void Traversal(TreeNode* cur, vector<int>& v)
{
if (cur == nullptr) return;
v.push_back(cur->val);
Traversal(cur->left, v);
Traversal(cur->right, v);
}
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res;
Traversal(root, res);
return res;
}
};
后序遍历
class Solution {
public:
void Traversal(TreeNode* cur, vector<int>& v)
{
if (cur == nullptr) return;
Traversal(cur->left, v);
Traversal(cur->right, v);
v.push_back(cur->val);
}
vector<int> postorderTraversal(TreeNode* root) {
vector<int> res;
Traversal(root, res);
return res;
}
};
中序遍历
class Solution {
public:
void Treversal(TreeNode* cur, vector<int>& v)
{
if (cur == nullptr) return;
Treversal(cur->left, v);
v.push_back(cur->val);
Treversal(cur->right, v);
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
Treversal(root, res);
return res;
}
};
迭代遍历二叉树
题目同上
对于前序遍历,它的顺序是中左右,每次需先处理中间节点,那么现将根节点入栈中,然后将右孩子放入栈,再将左孩子加入栈。因为我们需要中左右,所以需先把右孩子放入栈,这样先出来的就是左孩子。而后序遍历只需先放入左孩子,再放入右孩子即可。
对于中序遍历则与上两个不同,上两种情况要访问的元素和要处理的元素顺序是一致的,而中序遍历是左中右。遍历先访问的是根节点,要处理的确实最底部的左节点,两个顺序不一致。所以就要从新编写规则。
前序遍历
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
vector<int> res;
if (root == nullptr) return res;
st.push(root);
while (!st.empty())
{
TreeNode* cur = st.top();
st.pop();
res.push_back(cur->val);
if (cur->right) st.push(cur->right);
if (cur->left) st.push(cur->left);
}
return res;
}
};
后序遍历
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
vector<int> res;
if (root == nullptr) return res;
st.push(root);
while (!st.empty())
{
TreeNode* cur = st.top();
st.pop();
res.push_back(cur->val);
if (cur->left) st.push(cur->left);
if (cur->right) st.push(cur->right);
} // 执行完是中右左的顺序
reverse(res.begin(), res.end()); // 要把结果反转才是左右中的顺序
return res;
}
};
中序遍历
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
vector<int> res;
TreeNode* cur = root;
while (!st.empty() || cur != nullptr)
{
if (cur != nullptr) // 从左边一直遍历,并把节点放入栈中
{
st.push(cur);
cur = cur->left;
}
else
{
cur = st.top();
st.pop();
res.push_back(cur->val);
cur = cur->right;
}
}
return res;
}
};