您现在的位置是:首页 >技术交流 >【数据结构与算法】力扣:二叉树的前、中、后序遍历网站首页技术交流
【数据结构与算法】力扣:二叉树的前、中、后序遍历
简介【数据结构与算法】力扣:二叉树的前、中、后序遍历
递归法
前序遍历
给你二叉树的根节点 root ,返回它节点值的前序 遍历。
示例 1:
输入:root = [1,null,2,3]
输出:[1,2,3]
示例 2:
输入:root = []
输出:[]
示例 3:
输入:root = [1]
输出:[1]
示例 4:
输入:root = [1,2]
输出:[1,2]
示例 5:
输入:root = [1,null,2]
输出:[1,2]
提示:
树中节点数目在范围 [0, 100] 内
-100 <= Node.val <= 100
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/binary-tree-preorder-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
分析
递归:
1.规定递归的函数的参数和返回值
参数:一个指针TreeNode* cur
返回值:结果是一个数组:vector<int>& vec
2.确定终止条件。深度优先搜索,遇到空指针才停止
if(cur == NULL)
return;
3.确定单层递归的逻辑
vec.push(cur->val);//根
traversal(cur->left,vec);//左
traversal(cur->right,vec);//右
代码
/**
* 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;
}
};
中序遍历
代码
/**
* 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;
}
traversal(cur->left,vec);
vec.push_back(cur->val);
traversal(cur->right,vec);
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
traversal(root,result);
return result;
}
};
后序遍历
/**
* 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;
traversal(cur->left,vec);
traversal(cur->right,vec);
vec.push_back(cur->val);
}
vector<int> postorderTraversal(TreeNode* root) {
vector<int> result;
traversal(root,result);
return result;
}
};
迭代法
前序遍历(根左右)
【分析】编程语言中,常用“栈”来实现递归,用迭代法模拟递归也用栈。
代码
/**
* 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:
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*> st;//定义一个栈保存树中的结点
vector<int> res;
if(root == NULL) return res;
st.push(root);//先把根结点放入栈中
while(!st.empty())
{
TreeNode* node = st.top();//树的根节点就是栈顶元素
st.pop();//将当前栈顶元素弹出
res.push_back(node->val);
if(node->right)st.push(node->right);//将栈顶元素的右孩子入栈
if(node->left)st.push(node->left);//将栈顶元素的左孩子入栈
}
//一遍遍历结束,到了左子树的根节点,即上一个结点的左孩子,即此时栈的栈顶元素
return res;
}
};
后序遍历(左右根)
上文中前序遍历的顺序是:中->左->右
改为:中->右->左
再翻转数组:左->右->中
代码
/**
* 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:
vector<int> postorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
vector<int> res;
//vector<int> rres;
if(root == NULL)return res;
st.push(root);
while(!st.empty())
{
TreeNode* node = st.top();
st.pop();
res.push_back(node->val);
if(node->left) st.push(node->left);
if(node->right) st.push(node->right);
}
reverse(res.begin(),res.end());
return res;
}
};
中序遍历
左孩子为空将栈顶元素加到数组里;右孩子为空,弹出栈顶元素。
模拟例子中的步骤
- 从根节点开始向左遍历。根节点为5
cur = root;
- 一直到遍历到最左端,一路向左,将指针经过的所有左结点放入栈中,直到再无左结点可遍历时停止。当栈为空时,也停止遍历。将5、4、1依次放入栈中
while(cur!=NULL || !st.empty())
{
if(cur != NULL)
{
st.push(cur);
cur = cur->left;
}
- 访问到最左端结点1,1没有左孩子了。取栈顶结点1(即最近访问过的结点),将其弹出栈,加入到数组(加入到数组的结点都是要处理的),遍历此时取出来的栈顶结点1的右孩子
else
{
cur = st.top();
st.pop();
res.push_back(cur->val);
cur = cur->right;
}
}
- 结点1的右孩子也为空,执行的还是else分支,即弹出栈顶元素,此时栈顶元素为4,将4加入数组,处理结点4,
4的右孩子
为2 - 此时cur->val=2,执行if分支,将2加入栈中
- 执发现2的左孩子为空,执行else,弹出栈顶元素2,并加入数组,发现2的右孩子也为空
- 执行else取此时栈顶元素5,将5加入数组,取5的右孩子6
- 执行if将6入栈并发现6无左孩子,执行else,将6弹出栈,最终栈空,循环停止,程序结束
对于第一遍遍历就存在栈中的元素,取出来放到数组中时要做的操作的只有访问右节点,但是若其含有右节点则需要将其右节点从头执行循环,要新加入栈中。即对于不是第一遍遍历就在栈中的节点,会多了个if操作
代码
/**
* 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:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
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();//将其弹出栈 放入数组
res.push_back(cur->val);
cur = cur->right;//遍历当前指针的右孩子
}
}
return res;
}
};
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。