目录
利用递归遍历二叉树,在遍历每个节点的不同位置打印对应不同的遍历顺序。
一、先序遍历(对于每一颗子树先打印头结点,再打印左节点,最后打印右节点)
二、中序遍历(对于每一颗子树先打印左节点,再打印头节点,最后打印右节点)
三、后序遍历(对于每一颗子树先打印左节点,再打印右节点,最后打印头节点)
二叉树数据结构定义
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) {}
};
利用递归遍历二叉树,在遍历每个节点的不同位置打印对应不同的遍历顺序。
void f(TreeNode *head, vector<int>& ans){
//第一次进入该节点
if(head == nullptr)
return;
//第一次回到自己
f(head->left, ans);
//第二次进入该节点
//第二次回到自己
f(head->right, ans);
//第三次进入该节点
//第三次回到自己
}
一、先序遍历(对于每一颗子树先打印头结点,再打印左节点,最后打印右节点)
深度优先遍历即为先序遍历
1、递归遍历
第一次遍历到每个节点时打印对应先序遍历。
vector<int> ans 中存放的就是对应的遍历顺序。
//递归函数
void f(TreeNode *head, vector<int>& ans){
if(head == nullptr)
return;
ans.push_back(head->val);
f(head->left, ans);
f(head->right, ans);
}
//调用递归,返回前序遍历顺序
vector<int> preorderTraversal(TreeNode* root) {
vector<int> ans;
f(root, ans);
return ans;
}
2、非递归的方式进行先序遍历(利用栈)
整体流程
先给栈中压入根节点
(栈不为空循环下述操作)
- 弹出栈中节点
- 对该节点进行操作
- 将节点右节点和左节点先后压入栈中(没有跳过)
vector<int> preorderTraversal(TreeNode* root) {
vector<int> ans;
stack<TreeNode*> stackTreeNode;
if(root == NULL) return {};
stackTreeNode.push(root);
while(stackTreeNode.size()){
TreeNode *cur = stackTreeNode.top();
stackTreeNode.pop();
ans.push_back(cur->val);
if(cur->right != NULL) stackTreeNode.push(cur->right);
if(cur->left != NULL) stackTreeNode.push(cur->left);
}
return ans;
}
二、中序遍历(对于每一颗子树先打印左节点,再打印头节点,最后打印右节点)
1、递归遍历
第二次遍历到每个节点时打印对应中序遍历。
void f(TreeNode *head, vector<int>& ans){
if(head == nullptr)
return;
f(head->left, ans);
ans.push_back(head->val);
f(head->right, ans);
}
2、非递归的方式进行中序遍历(利用栈)
整体流程
压入顺序左右头
每棵树左边界压入栈,依次弹出节点的过程中对弹出节点的右树重复上述操作。
(栈1不为空循环下述操作)
- 弹出栈中节点
- 对该节点进行操作
- 对该节点右树重复
vector<int> inorderTraversal(TreeNode* root) {
vector<int> ans;
if(root == NULL) return {};
stack<TreeNode*> s;
TreeNode *cur = root;
while(s.size() || cur!= NULL)
{
if(cur != NULL){
s.push(cur);
cur = cur->left;
}
else{
cur = s.top();
s.pop();
ans.push_back(cur->val);
cur = cur->right;
}
}
return ans;
}
三、后序遍历(对于每一颗子树先打印左节点,再打印右节点,最后打印头节点)
1、递归遍历
第三次遍历到每个节点时打印对应后序遍历。
void f(TreeNode *head, vector<int>& ans){
if(head == nullptr)
return;
f(head->right, ans);
f(head->left, ans);
ans.push_back(head->val);
}
2、非递归的方式进行后序遍历(利用栈)
整体流程
需要两个栈
先给栈1中压入根节点
(栈1不为空循环下述操作)
- 弹出栈1中节点
- 对该节点进行操作
- 将该节点放入栈1
- 将节点左节点和右节点先后压入栈1中(没有跳过)
vector<int> postorderTraversal(TreeNode* root) {
vector<int> ans;
if(root == NULL) return {};
stack<TreeNode*> s1;
stack<TreeNode*> s2;
s1.push(root);
while(s1.size()){
TreeNode *cur = s1.top();
s1.pop();
s2.push(cur);
if(cur->left!=NULL) s1.push(cur->left);
if(cur->right!=NULL) s1.push(cur->right);
}
while(s2.size())
{
TreeNode *cur = s2.top();
ans.push_back(cur->val);
s2.pop();
}
return ans;
}
四、宽度优先遍历(利用栈逐层遍历)
void levelOrder(TreeNode* root) {
if(root == NULL) return;
queue<TreeNode*> q;
q.push(root);
while(q.size())
{
TreeNode *cur = q.front();
q.pop();
if(cur->left != NULL) q.push(cur->left);
if(cur->right != NULL) q.push(cur->right);
}
return;
}