理论基础
在LeetCode中有默认头结点定义
/**
* 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) {}
* };
*/
遍历方法的不同就是优先遍历前中后的顺序不同
前序遍历
1.递归写法
class Solution {
public:
void traversal(TreeNode* cur, vector<int>& result) {
if (cur == nullptr) {
return;
}
result.push_back(cur->val);中左右
traversal(cur->left, result);
traversal(cur->right, result);
}
vector<int> preorderTraversal(TreeNode* root) {
vector<int>result;
traversal(root,result);
return result;
}
};
方法及步骤
- 确定参数和返回值,参数一般都是要什么写什么,返回值一般是void
- 确定终止条件,防止栈溢出,一般都是到最后为空的时候结束
- 确定单层递归的逻辑,中左右等
关键:
每遇到新结点都先加入,按左遍历,为什么后面不会向左遍历了而回溯向右遍历呢,因为按照递归顺序,向左遍历的那一层已经运行完了,
下面的栈是删除左结点再遍历到右结点,而这个是运行完了那一行回溯才会遍历到右节点
2.栈的迭代写法
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int>result;
stack<TreeNode*>st;
if (root == nullptr) return result;
TreeNode* cur = root;
st.push(cur);//先加入第一个元素
while(!st.empty()) {
TreeNode*cur = st.top();
st.pop();//取完值就可以去掉了
result.push_back(cur->val);
if (cur->right) st.push(cur->right);//加入右边(和栈的输出有关)
if (cur->left) st.push(cur->left); //加入左边
}//弹出一个就加入右边和左边,就能访问到最底层
return result;
}
};
图像理解
思路和步骤
先序遍历是先输出才会进行遍历,遵循中左右的顺序,这里是用栈实现的步骤
1.必须先定义一个vector<int>result来储存结果集,用stack<TreeNode*>st来储存遍历结点,再用TreeNode*cur=root来标记遍历到哪里了
2.r如果题目一开始给的二叉树就为空,我们就输出空的容器result
3.后面需要把其实位置加入栈中st.push(cur)
4.确定while的的条件(遍历完整棵二叉树的条件)while(!st.empty())
5.中:取出最前面的元素,输出它代表的值。并删除它(输出代表遍历完了用不到了),cur = st.top();st.pop(),result.push_back(cur->val)
6.左;先进右,因为栈是先输出后面加入的,所以if(cur->right) st.push(cur->right)
7.if(cur->left) st.push(cur->left)
8.输出结果集
关键
当输出完这个结点时这个结点必定在栈中移除了,下次进行到第六步第七步后他会自动跳到没有输出的右结点。
比如上面一张图的5,4,1,2,6.每次加进去都是会输出左结点,后面把左节点删除,最后只剩下了右结点没有删除,可以从下向上删除右结点了,再输出
中序遍历
1.递归写法
/**
* 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>& result) {
if (cur ==nullptr) {
return;
}
traversal(cur->left, result);
result.push_back(cur->val);
traversal(cur->right, result);
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int>result;
traversal(root, result);
return result;
}
};
步骤:和前序差不多,就是顺序变了
关键:
运行完这个结点的左子树才会输出
2.栈写法
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int>result;
stack<TreeNode*>st;
TreeNode* cur = root;
while (cur != NULL || !st.empty()) {
if (cur != NULL) {
st.push(cur);
cur = cur->left;//左
} else {
cur = st.top();
st.pop();
result.push_back(cur->val);//中
cur = cur->right;//右
}
}
return result;
}
};
步骤和思路
1.和前序一样前面vector<int>result,stack<TreeNode*>st,TreeNode*cur=root
2.两个条件,看把栈全部清楚了没,清除完就结束了,!st.empty()
3.左:直接访问到最后一层结束,cur=cur->left
4.中,输出删除
5.右:到右结点
6.输出
具体解答看代码随想录
后序遍历
1.递归写法
/**
* 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>& result) {
if (cur == nullptr) {
return;
}//当遍历到不存在的点时
traversal(cur->left, result);
traversal(cur->right, result);
result.push_back(cur->val);
}
vector<int> postorderTraversal(TreeNode* root) {
vector<int>result;
traversal(root, result);
return result;
}
};
2.栈遍历
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int>result;
stack<TreeNode*> st;
TreeNode* cur = root;
if (root == NULL) return result;
st.push(cur);
while(!st.empty()) {
TreeNode* cur = st.top();
st.pop();
result.push_back(cur->val);
if (cur->left) st.push(cur->left);
if (cur->right) st.push(cur->right);
}
reverse(result.begin(),result.end());
return result;
}
};
解释:
先写完先序遍历,再交换左右就变成了,中右左,最后再reverse一下变成了左右中就是倒序输出了。