当前位置:   article > 正文

二叉树的层序遍历 bfs(通过队列实现bfs)_层次遍历与bfs

层次遍历与bfs

 队列元素从队尾进,从队头出

 

树形bfs

核心:

step1:将队头节点移出队列

step2:然后将这个结点的左右孩子结点加入队列

  1. Queue queue = new LinkedList();
  2. //先将根节点加入队列
  3. queue.add(root);
  4. //只要队列里还存在元素
  5. while(queue.size()!=0)
  6. {
  7. //求出队列中此时有几个元素,这些元素都要出队列,而且出队列后要把它们的左右孩子都加入队列
  8. int size=queue.size();
  9. for(int i=0;i<size;i++)
  10. {
  11. Node current=queue.remove();//将队头结点移出队列
  12. //将刚刚移出队列的结点的左右孩子结点加入队列
  13. if(current.left!=null)
  14. {
  15. queue.add(current.left);
  16. }
  17. if(current.right!=null)
  18. {
  19. queue.add(current.right);
  20. }
  21. }
  22. }

每一轮size是多少,就说明这一层有多少个结点




102

非递归解法:

(1) 这里有个核心:每一轮开始的时候(把上一轮的节点全部出队列之后)都会计算此时队列的长度,此时队列的长度就是二叉树某一层的节点个数,将这一层的节点值全部添加到临时arraylist中,然后开始下一轮(也就是下一层)

也就是说这就是在遍历每一层

(2)每次出队列1个结点,就把这个结点的左右孩子都入队列,每一轮将一层结点出队列

  1. class Node
  2. {
  3. int val;
  4. Node left;
  5. Node right;
  6. public Node(int val)
  7. {
  8. this.val=val;
  9. }
  10. }
  11. class Solution
  12. {
  13. //传入根节点
  14. public static ArrayList levelOrderTraverse(Node root)
  15. {
  16. //最后的结果数组是“数组的数组”形式
  17. //比如:[[1],[2,3],[4,5,6,7]]
  18. ArrayList result=new ArrayList();
  19. if(root==null)
  20. {
  21. return result;
  22. }
  23. //创建队列,队列里装的是结点
  24. Queue queue=new LinkedList();
  25. //将根节点入队列,此时root就是队头结点
  26. queue.offer(root);
  27. //只要队列不为空,就一直循环(开始时队列中有头结点这一个数,队列不为空,进入循环)
  28. while(queue.isEmpty()==false)
  29. {
  30. //统计出此时队列的长度,此时队列的长度是多少,就说明这一层有几个结点,这句话非常非常非常关键
  31. int size=queue.size();
  32. //每一层的节点的值用一个数组来装,装完一层就把这个数组添加到结果数组中
  33. //注意里面装的是结点的值,不是结点
  34. ArrayList temp=new ArrayList();
  35. //每一轮把一层的结点全部弹出队列,并且把这一层结点的左右孩子结点全部加进队列
  36. for(int i=0;i<size;i++)
  37. {
  38. //queue.poll()方法表示返回队头元素,并且在队列中删除
  39. // 所以这里会把队头结点删除并且赋给current
  40. Node current=(Node)queue.poll();
  41. //将刚刚删除的队头结点的值添加到temp数组中
  42. temp.add(current.val);
  43. if(current.left!=null)
  44. {
  45. queue.add(current.left);
  46. }
  47. if(current.right!=null)
  48. {
  49. queue.add(current.right);
  50. }
  51. }
  52. result.add(temp);
  53. }
  54. return result;
  55. }
  56. }
  57. public class test
  58. {
  59. public static void main(String[] args) {
  60. Node root = new Node(1);
  61. root.left = new Node(2);
  62. root.right = new Node(3);
  63. root.left.left = new Node(4);
  64. root.right.right = new Node(8);
  65. Solution solution = new Solution();
  66. ArrayList a = solution.levelOrderTraverse(root);
  67. System.out.println(a);
  68. //[[1], [2, 3], [4, 8]]
  69. }
  70. }

 核心代码就是这一段:核心就是需要将每一个移出队列的结点的左右孩子结点加入队列

  1. Queue queue = new LinkedList();
  2. //先将根节点加入队列
  3. queue.add(root);
  4. //只要队列里还存在元素
  5. while(queue.isEmpty()==false)
  6. {
  7. //求出队列中此时有几个元素,这些元素都要出队列,而且出队列后要把它们的左右孩子都加入队列
  8. int size=queue.size();
  9. for(int i=0;i<size;i++)
  10. {
  11. Node current=queue.remove();//将队头结点移出队列
  12. //将刚刚移出队列的结点的左右孩子结点加入队列
  13. if(current.left!=null)
  14. {
  15. queue.add(current.left);
  16. }
  17. if(current.right!=null)
  18. {
  19. queue.add(current.right);
  20. }
  21. }
  22. }

如果是429. N 叉树的层序遍历 - 力扣(LeetCode)

只需将核心代码改成:

  1. Node current=(Node)queue.poll();
  2. //将刚刚删除的队头结点的值添加到temp数组中
  3. temp.add(current.val);
  4. for(Node child:node.children)
  5. {
  6. if(child!=null)
  7. {
  8. queue.add(child);
  9. }
  10. }

也就是说将队列中一个节点出队列后,不是将这个节点的左右孩子节点入队,而是需要将这个节点的所有孩子节点都入队

  1. class Solution
  2. {
  3. public List<List<Integer>> levelOrder(Node root)
  4. {
  5. ArrayList result=new ArrayList();
  6. if(root==null)
  7. {
  8. return result;
  9. }
  10. Queue<Node> queue=new LinkedList();
  11. queue.offer(root);
  12. //队列不为空,就要继续
  13. while(queue.isEmpty()==false)
  14. {
  15. int size=queue.size();
  16. ArrayList temp=new ArrayList();
  17. for(int i=0;i<size;i++)
  18. {
  19. Node current=queue.poll();
  20. temp.add(current.val);
  21. for(Node child:current.children)
  22. {
  23. if(child!=null)
  24. {
  25. queue.add(child);
  26. }
  27. }
  28. }
  29. result.add(temp);
  30. }
  31. return result;
  32. }
  33. }

107. 二叉树的层序遍历 II - 力扣(LeetCode)

只需将二叉树层序遍历的得到的数组进行反转即可

即多加上这句代码就可以了:

Collections.reverse(result);
  1. class Solution
  2. {
  3. public List<List<Integer>> levelOrderBottom(TreeNode root)
  4. {
  5. List<List<Integer>> result=new ArrayList();
  6. if(root==null)
  7. {
  8. return result;
  9. }
  10. Queue<TreeNode> queue=new LinkedList();
  11. queue.offer(root);
  12. //队列不为空,就要继续
  13. while(queue.isEmpty()==false)
  14. {
  15. int size=queue.size();
  16. List<Integer> temp=new ArrayList();
  17. for(int i=0;i<size;i++)
  18. {
  19. TreeNode current=queue.poll();
  20. temp.add(current.val);
  21. if(current.left!=null)
  22. {
  23. queue.add(current.left);
  24. }
  25. if(current.right!=null)
  26. {
  27. queue.add(current.right);
  28. }
  29. }
  30. result.add(temp);
  31. }
  32. Collections.reverse(result);
  33. return result;
  34. }
  35. }

199. 二叉树的右视图 - 力扣(LeetCode)

其实就是把每一层的最后一个元素加入到列表中返回

  1. class Solution
  2. {
  3. public List<Integer> rightSideView(TreeNode root)
  4. {
  5. List<Integer> result=new ArrayList();
  6. if(root==null)
  7. {
  8. return result;
  9. }
  10. Queue<TreeNode> queue=new LinkedList();
  11. queue.offer(root);
  12. //队列不为空,就要继续
  13. while(queue.isEmpty()==false)
  14. {
  15. int size=queue.size();
  16. for(int i=0;i<size;i++)
  17. {
  18. TreeNode current=queue.poll();
  19. if(i==size-1)
  20. {
  21. result.add(current.val);
  22. }
  23. if(current.left!=null)
  24. {
  25. queue.add(current.left);
  26. }
  27. if(current.right!=null)
  28. {
  29. queue.add(current.right);
  30. }
  31. }
  32. }
  33. return result;
  34. }
  35. }

515. 在每个树行中找最大值 - 力扣(LeetCode)

  1. class Solution
  2. {
  3. public List<Integer> largestValues(TreeNode root)
  4. {
  5. List<Integer> result=new ArrayList();
  6. if(root==null)
  7. {
  8. return result;
  9. }
  10. Queue<TreeNode> queue=new LinkedList();
  11. queue.offer(root);
  12. //每一轮负责找出一层的二叉树的节点
  13. while(queue.isEmpty()==false)
  14. {
  15. int size=queue.size();
  16. int temp=Integer.MIN_VALUE;
  17. for(int i=0;i<size;i++)
  18. {
  19. TreeNode current=queue.poll();
  20. if(current.val>temp)
  21. {
  22. temp=current.val;
  23. }
  24. if(current.left!=null)
  25. {
  26. queue.add(current.left);
  27. }
  28. if(current.right!=null)
  29. {
  30. queue.add(current.right);
  31. }
  32. }
  33. result.add(temp);
  34. }
  35. return result;
  36. }
  37. }

637. 二叉树的层平均值 - 力扣(LeetCode)

  1. class Solution
  2. {
  3. public List<Double> averageOfLevels(TreeNode root)
  4. {
  5. List result=new ArrayList();
  6. if(root==null)
  7. {
  8. return result;
  9. }
  10. Queue<TreeNode> queue=new LinkedList();
  11. queue.offer(root);
  12. //每一轮负责找出一层的二叉树的节点
  13. while(queue.isEmpty()==false)
  14. {
  15. int size=queue.size();
  16. double temp=0;
  17. for(int i=0;i<size;i++)
  18. {
  19. TreeNode current=queue.poll();
  20. temp=temp+current.val;
  21. if(current.left!=null)
  22. {
  23. queue.add(current.left);
  24. }
  25. if(current.right!=null)
  26. {
  27. queue.add(current.right);
  28. }
  29. }
  30. temp=temp/size;
  31. result.add(temp);
  32. }
  33. return result;
  34. }
  35. }

117. 填充每个节点的下一个右侧节点指针 II - 力扣(LeetCode)

  1. class Solution
  2. {
  3. public Node connect(Node root)
  4. {
  5. List result=new ArrayList();
  6. if(root==null)
  7. {
  8. return root;
  9. }
  10. Queue<Node> queue=new LinkedList();
  11. queue.offer(root);
  12. //每一轮负责找出一层的二叉树的节点
  13. while(queue.isEmpty()==false)
  14. {
  15. int size=queue.size();
  16. Node dummy=new Node(-1);
  17. for(int i=0;i<size;i++)
  18. {
  19. Node current=queue.poll();
  20. dummy.next=current;
  21. dummy=current;
  22. if(current.left!=null)
  23. {
  24. queue.add(current.left);
  25. }
  26. if(current.right!=null)
  27. {
  28. queue.add(current.right);
  29. }
  30. }
  31. }
  32. return root;
  33. }
  34. }

力扣103 二叉树的锯齿形层次遍历

就是增加一个标志位flag,flag=1,奇数行,那就不反转列表

                                          flag=0,偶数行,反转列表

  1. class Solution
  2. {
  3. public List<List<Integer>> zigzagLevelOrder(TreeNode root)
  4. {
  5. List<List<Integer>> result=new ArrayList();
  6. if(root==null)
  7. {
  8. return result;
  9. }
  10. Queue<TreeNode> queue=new LinkedList();
  11. queue.offer(root);
  12. int flag=1;
  13. //队列不为空,就要继续
  14. while(queue.isEmpty()==false)
  15. {
  16. int size=queue.size();
  17. List<Integer> temp=new ArrayList();
  18. for(int i=0;i<size;i++)
  19. {
  20. TreeNode current=queue.poll();
  21. temp.add(current.val);
  22. if(current.left!=null)
  23. {
  24. queue.add(current.left);
  25. }
  26. if(current.right!=null)
  27. {
  28. queue.add(current.right);
  29. }
  30. }
  31. if(flag<0) Collections.reverse(temp);
  32. flag=-flag;
  33. result.add(temp);
  34. }
  35. return result;
  36. }
  37. }

 力扣1161 求出和最大的那一层层号

  1. class Solution
  2. {
  3. public int maxLevelSum(TreeNode root)
  4. {
  5. int num=1;//统计当前到了第几层
  6. int result=1;
  7. int sum=Integer.MIN_VALUE;//预防每个节点值都是负数情况
  8. Queue<TreeNode> queue=new LinkedList();
  9. queue.offer(root);
  10. //每一轮负责找出一层的二叉树的节点
  11. while(queue.isEmpty()==false)
  12. {
  13. int size=queue.size();
  14. int temp=0;
  15. for(int i=0;i<size;i++)
  16. {
  17. TreeNode current=queue.poll();
  18. temp=temp+current.val;
  19. if(current.left!=null)
  20. {
  21. queue.add(current.left);
  22. }
  23. if(current.right!=null)
  24. {
  25. queue.add(current.right);
  26. }
  27. }
  28. if(temp>sum)
  29. {
  30. sum=temp;
  31. result=num;
  32. }
  33. num++;//nums用来记录层数,表示到了第几层
  34. }
  35. return result;
  36. }
  37. }

力扣513 找树左下角的值(二叉树最底层最左边的值)

  1. class Solution
  2. {
  3. public int findBottomLeftValue(TreeNode root)
  4. {
  5. ArrayList<ArrayList<Integer>> result=new ArrayList();
  6. Queue queue=new LinkedList();
  7. queue.offer(root);
  8. while(queue.isEmpty()==false)
  9. {
  10. int size=queue.size();
  11. ArrayList temp=new ArrayList();
  12. for(int i=0;i<size;i++)
  13. {
  14. TreeNode current=(TreeNode)queue.poll();
  15. temp.add(current.val);
  16. if(current.left!=null)
  17. {
  18. queue.add(current.left);
  19. }
  20. if(current.right!=null)
  21. {
  22. queue.add(current.right);
  23. }
  24. }
  25. result.add(temp);
  26. }
  27. return result.get(result.size()-1).get(0);
  28. }
  29. }

力扣1302 层数最深叶子节点的和

  1. class Solution
  2. {
  3. public int deepestLeavesSum(TreeNode root)
  4. {
  5. ArrayList<ArrayList<Integer>> result=new ArrayList();
  6. Queue queue=new LinkedList();
  7. queue.offer(root);
  8. while(queue.isEmpty()==false)
  9. {
  10. int size=queue.size();
  11. ArrayList temp=new ArrayList();
  12. for(int i=0;i<size;i++)
  13. {
  14. TreeNode current=(TreeNode)queue.poll();
  15. temp.add(current.val);
  16. if(current.left!=null)
  17. {
  18. queue.add(current.left);
  19. }
  20. if(current.right!=null)
  21. {
  22. queue.add(current.right);
  23. }
  24. }
  25. result.add(temp);
  26. }
  27. int num=0;
  28. for(int i=0;i<result.get(result.size()-1).size();i++)
  29. {
  30. num=num+ result.get(result.size()-1).get(i);
  31. }
  32. return num;
  33. }
  34. }

图bfs:

存储图的两种方式:邻接矩阵和邻接表

 力扣 542  01矩阵

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

闽ICP备14008679号