二叉树遍历
遍历二叉树
二叉树主要有两种遍历方式:
- 深度优先遍历:先往深走,遇到叶子节点再往回走。
- 广度优先遍历:一层一层的去遍历。
从深度优先遍历和广度优先遍历进一步拓展,才有如下遍历方式:
- 深度优先遍历
- 前序遍历(递归法,迭代法)
- 中序遍历(递归法,迭代法)
- 后序遍历(递归法,迭代法)
- 广度优先遍历
- 层次遍历(迭代法)
这里前中后,其实指的就是中间节点的遍历顺序
- 前序遍历:中左右
- 中序遍历:左中右
- 后序遍历:左右中
实现方式
深度搜索:栈其实就是递归的一种实现结构,也就说前中后序遍历的逻辑其实都是可以借助栈使用递归的方式来实现的。
广度搜索:使用队列来实现,这也是队列先进先出的特点所决定的,因为需要先进先出的结构,才能一层一层的来遍历二叉树。
二叉树的前序遍历
每次写递归,都按照这三要素来写:
- 确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。
- 确定终止条件: 写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。
- 确定单层递归的逻辑: 确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。
以前序遍历为例
- 确定递归函数的参数和返回值:因为要打印出前序遍历节点的数值,所以参数里需要传入vector来放节点的数值,除了这一点就不需要再处理什么数据了也不需要有返回值,所以递归函数返回类型就是void,代码如下:
void traversal(TreeNode* cur, vector<int>& vec)
- 确定终止条件:在递归的过程中,如何算是递归结束了呢,当然是当前遍历的节点是空了,那么本层递归就要结束了,所以如果当前遍历的这个节点是空,就直接return,代码如下:
if (cur == NULL) return;
- 确定单层递归的逻辑:前序遍历是中左右的循序,所以在单层递归的逻辑,是要先取中节点的数值,代码如下
vec.push_back(cur->val); // 中
traversal(cur->left, vec); // 左
traversal(cur->right, vec); // 右
v1.0: 简单
/**
* 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(vector<int> &ret, TreeNode *cur)
{
if(cur==nullptr)return;
ret.push_back(cur->val);
traversal(ret, cur->left);
traversal(ret, cur->right);
}
vector<int> preorderTraversal(TreeNode* root) {
vector<int> result;
TreeNode *cur = root;
traversal(result, cur);
return result;
}
};
v2.0:迭代法
v2.0:迭代法:建立一个装树的节点的栈,然后更新栈时把夫节点取出,放入子节点即可
/**
* 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) {
vector<int> result;
if (root == NULL) return result;
stack<TreeNode*> stk;
stk.push(root);
while(!stk.empty())
{
TreeNode * cur = stk.top();
stk.pop();
result.push_back(cur->val);
if(cur->right)stk.push(cur->right);
if(cur->left)stk.push(cur->left);
}
return result;
}
};
复习:递归法
void traversal(TreeNode* cur, vector<int> &v)
{
if (cur == nullptr)
return;
v.emplace_back(cur->val);
traversal(cur->left,v);
traversal(cur->right,v);
}
vector<int> preorderTraversal(TreeNode* root) {
vector<int> ret;
traversal(root, ret);
return ret;
}
复习:统一迭代法
vector<int> preorderTraversal(TreeNode* root) {
vector<int> ret;
stack<TreeNode*> s;
if(root)
s.push(root);
while (!s.empty())
{
TreeNode* cur = s.top();
if (cur != nullptr)
{
s.pop();
if (cur->right)
s.push(cur->right);
if (cur->left)
s.push(cur->left);
s.push(cur);
s.push(nullptr);
}
else
{
s.pop();
ret.emplace_back(s.top()->val);
s.pop();
}
}
return ret;
}
二叉树的中序遍历
v1.0:注意理解递归的思想,递归就是套娃,递归到叶子节点就会返回
/**
* 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(vector<int> &ret, TreeNode *cur)
{
if(cur==nullptr)return;
traversal(ret, cur->left);
ret.push_back(cur->val);
traversal(ret, cur->right);
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
traversal(result, root);
return result;
}
};
v2.0: 迭代
/**
* 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> result;
if(root==nullptr)return result;
stack<TreeNode*> stk;
TreeNode* cur = root;
while(cur||!stk.empty())
{
if(cur)
{
stk.push(cur);
cur=cur->left;
}else{
cur = stk.top();
stk.pop();
result.push_back(cur->val);
cur = cur->right;
}
}
return result;
}
};
复习:递归法
void traversal(TreeNode* cur, vector<int> &v)
{
if (cur == nullptr)
return;
traversal(cur->left, v);
v.emplace_back(cur->val);
traversal(cur->right,v);
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int> ret;
traversal(root, ret);
return ret;
}
复习:统一迭代法
vector<int> inorderTraversal(TreeNode* root) {
vector<int> ret;
stack<TreeNode*> s;
if(root)
s.push(root);
while (!s.empty())
{
TreeNode* cur = s.top();
if (cur != nullptr)
{
s.pop();
if (cur->right)
s.push(cur->right);
s.push(cur);
s.push(nullptr);
if (cur->left)
s.push(cur->left);
}
else
{
s.pop();
ret.emplace_back(s.top()->val);
s.pop();
}
}
return ret;
}
二叉树的后序遍历
v1.0:
/**
* 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(vector<int> &ret, TreeNode *cur)
{
if(cur==nullptr)return;
traversal(ret, cur->left);
traversal(ret, cur->right);
ret.push_back(cur->val);
}
vector<int> postorderTraversal(TreeNode* root) {
vector<int> result;
traversal(result, root);
return result;
}
};
v2.0:迭代法 因为后续遍历时右左中 把前序遍历变成中右左,最后再反转一下就行了
/**
* 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) {
vector<int> result;
if(root==nullptr)return result;
stack<TreeNode*> stk;
stk.push(root);
while(!stk.empty())
{
TreeNode *cur = stk.top();
stk.pop();
result.push_back(cur->val);
if(cur->left)stk.push(cur->left);
if(cur->right)stk.push(cur->right);
}
reverse(result.begin(), result.end());
return result;
}
};
复习:递归法
void traversal(TreeNode* cur, vector<int> &v)
{
if (cur == nullptr)
return;
traversal(cur->left, v);
traversal(cur->right,v);
v.emplace_back(cur->val);
}
vector<int> postorderTraversal(TreeNode* root) {
vector<int> ret;
traversal(root, ret);
return ret;
}
复习:统一迭代法
vector<int> postorderTraversal(TreeNode* root) {
vector<int> ret;
stack<TreeNode*> s;
if(root)
s.push(root);
while (!s.empty())
{
TreeNode* cur = s.top();
if (cur != nullptr)
{
s.pop();
s.push(cur);
s.push(nullptr);
if (cur->right)
s.push(cur->right);
if (cur->left)
s.push(cur->left);
}
else
{
s.pop();
ret.emplace_back(s.top()->val);
s.pop();
}
}
return ret;
}