当前位置:   article > 正文

二叉树的遍历(深度优先DFS/广度优先遍历BFS)_二叉树广度遍历

二叉树广度遍历

目录

1.概述

2.二叉树的深度优先遍历

2.1前序遍历

2.2中序遍历

2.3后序遍历

3.二叉树的广度优先遍历

3.1二叉树的广度优先遍历

3.2二叉树的层序遍历

3.3二叉树自底向上层序遍历

3.4二叉树的锯齿形层序遍历

1.概述

二叉树:一个节点只有一个入度和至多两个出度的图。

遍历方式:树/图的遍历分为深度优先搜索(DFS和广度优先遍历(BFS)。一般来说深度优先搜索的特点决定了深度优先搜索依赖于栈的实现,而广度优先搜索的实现依赖于队列的实现。

2.二叉树的深度优先遍历

关键词:递归、栈

2.1前序遍历

顺序:先根节点、然后左子树、右子树

  1. //递归版本
  2. void traversal(TreeNode* root, vector<int>& res) {
  3. if(root == nullptr)
  4. return;
  5. res.emplace_back(root->val);
  6. traversal(root->left, res);
  7. traversal(root->right, res);
  8. }
  9. vector<int> preorderTraversal(TreeNode* root) {
  10. vector<int> res;
  11. traversal(root, res);
  12. return res;
  13. }
  14. //非递归实现使用栈来保存遍历过的节点,不断入栈出栈直到栈空为止。 非递归实现与递归实现不同,遍历根节点后要先遍历右子树再遍历左子树(因栈的后进先出特性)
  15. vector<int> preorderTraversal(TreeNode* root) {
  16. vector<int> res;
  17. if(root == nullptr)
  18. return res;
  19. stack<TreeNode*> st;
  20. st.push(root);
  21. while (!st.empty()) {
  22. auto node = st.top();
  23. res.push_back(node->val);
  24. st.pop();
  25. if(node->right != nullptr)
  26. st.push(node->right);
  27. if(node->left != nullptr)
  28. st.push(node->left);
  29. }
  30. return res;
  31. }

2.2中序遍历

顺序:左子树--根节点--右子树

  1. #递归版本
  2. void travesal(TreeNode* root, vector<int>& res){
  3. if(!root)
  4. return;
  5. travesal(root->left,res);
  6. res.push_back(root->val);
  7. travesal(root->right, res);
  8. }
  9. vector<int> inorderTraversal(TreeNode* root) {
  10. vector<int> res;
  11. travesal(root, res);
  12. return res
  13. }
  14. #非递归实现,使用栈保存遍历过的节点,先找到最左节点然后依次出栈遍历节点对应的右子节点:
  15. vector<int> inorderTraversal(TreeNode* root) {
  16. vector<int> res;
  17. stack<TreeNode*> st;
  18. while (root != nullptr || !st.empty()) {
  19. while (root != nullptr) {
  20. st.push(root);
  21. root = root->left;
  22. }
  23. root = st.top();
  24. st.pop();
  25. res.push_back(root->val);
  26. root = root->right;
  27. }
  28. return res;
  29. }

2.3后序遍历

顺序:左子树--右子树--根节点

  1. #递归版本
  2. void traversal(TreeNode* root, vector<int>&res){
  3. if(root == nullptr)
  4. return;
  5. traversal(root->left, res);
  6. traversal(root->right, res);
  7. res.push_back(root->val);
  8. }
  9. vector<int> postorderTraversal(TreeNode* root) {
  10. vector<int> res;
  11. traversal(root, res);
  12. return res;
  13. }
  14. #非递归实现,使用栈保存遍历过的节点,先找到最右节点然后依次出栈遍历节点对应的左子节点,最后需要反转遍历结果:
  15. vector<int> postorderTraversal(TreeNode* root) {
  16. vector<int> res;
  17. if(root == nullptr)
  18. return res;
  19. stack<TreeNode*> st;
  20. TreeNode* prev = nullptr;
  21. while (!st.empty() || root != nullptr) {
  22. while(root != nullptr) {
  23. res.push_back(root->val);
  24. st.push(root);
  25. root = root->right;
  26. }
  27. root = st.top()->left;
  28. st.pop();
  29. }
  30. reverse(res.begin(), res.end());
  31. return res;
  32. }

3.二叉树的广度优先遍历

        二叉树的广度优先搜索类似于层序遍历:遍历跟节点,遍历左子节点和右子节点,然后遍历左子节点和它的左右子节点以及右子节点和它的左右子节点。广度优先搜索严格按照遍历的先后循序遍历节点,符合队列先进先出(FIFO)的特点,适合使用队列来实现。

3.1二叉树的广度优先遍历

  1. void bfs(TreeNode* root) {
  2. if(!root)
  3. return;
  4. queue<TreeNode*> que;
  5. que.push(root);
  6. while(!que.empty()){
  7. auto node = que.front();
  8. que.pop();
  9. cout << node->val << endl;
  10. if(node->left) que.push(node->left);
  11. if(node->right) que.push(node->right);
  12. }
  13. return res;
  14. }

3.2二叉树的层序遍历

不同点:需要对每层做一个标记

  1. #跟节点入队后加入一个空节点做哨兵,出队的时候发现是空节点就知道一层遍历结束了,保存本层结果继续加入空节点做哨兵。
  2. vector<vector<int>> levelOrder(TreeNode* root) {
  3. vector<vector<int>> res;
  4. if(!root)
  5. return res;
  6. queue<TreeNode*> que;
  7. que.push(root);
  8. que.push(nullptr);
  9. vector<int> temp;
  10. while(!que.empty()){
  11. auto node = que.front();
  12. que.pop();
  13. if(node){
  14. temp.push_back(node->val);
  15. if(node->left) que.push(node->left);
  16. if(node->right) que.push(node->right);
  17. }else if(!temp.empty()){
  18. res.push_back(temp);
  19. temp.clear();
  20. que.push(nullptr);
  21. }
  22. }
  23. return res;
  24. }

3.3二叉树自底向上层序遍历

路子:3.2自顶向下遍历后,逆置一下数组

  1. vector<vector<int>> levelOrderBottom(TreeNode* root) {
  2. vector<vector<int>> res;
  3. if(root == nullptr)
  4. return res;
  5. queue<TreeNode*> que;
  6. que.push(root);
  7. que.push(nullptr);
  8. vector<int> temp;
  9. while(!que.empty()){
  10. auto node = que.front();
  11. que.pop();
  12. if(node){
  13. temp.push_back(node->val);
  14. if(node->left) que.push(node->left);
  15. if(node->right) que.push(node->right);
  16. }else if(!temp.empty()){
  17. res.push_back(temp);
  18. temp.clear();
  19. que.push(nullptr);
  20. }
  21. }
  22. reverse(res.begin(), res.end());
  23. return res;
  24. }

3.4二叉树的锯齿形层序遍历

路子:只需要在层序遍历基础上加上一个标志,需要逆序时逆置一下该层遍历结果就可以了。

  1. vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
  2. vector<vector<int>> res;
  3. if(!root)
  4. return res;
  5. queue<TreeNode*> que;
  6. que.push(root);
  7. que.push(nullptr);
  8. vector<int> temp;
  9. bool change = false;
  10. while(!que.empty()){
  11. auto node = que.front();
  12. que.pop();
  13. if(node){
  14. temp.push_back(node->val);
  15. if(node->left) que.push(node->left);
  16. if(node->right) que.push(node->right);
  17. }else if(!temp.empty()){
  18. if(change)
  19. reverse(temp.begin(), temp.end());
  20. res.push_back(temp);
  21. temp.clear();
  22. que.push(nullptr);
  23. change = !change;
  24. }
  25. }
  26. return res;
  27. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/人工智能uu/article/detail/888010
推荐阅读
相关标签
  

闽ICP备14008679号