【问题标题】:How do I store level of each node while traversing in BFS?在 BFS 中遍历时如何存储每个节点的级别?
【发布时间】:2014-01-03 11:08:17
【问题描述】:

如果我们有一棵二叉树:

      7
    /  \
   5    6
  /\    /\
 2  3   1 4
   /
  5

如何打印以下输出?

[7],
[5,6]
[2,3,1,4]
[5]

意味着做一个 BFS 并将每个级别的节点存储在一个列表中,然后打印该列表?

我能够在 BFS 中遍历,但我无法找到树中每个元素的正确级别。

如何找到每个节点的正确级别,并使用节点对象的级别值丰富节点对象?

这是我的逻辑:

  1. BFS 中的遍历

  2. 用其级别值丰富树的每个节点

  3. 在列表中存储节点

  4. 遍历列表,创建<Level,List<Node>>的Map

  5. 将节点级别存储在Set<Integer> 中,然后转换为列表并对其进行排序。

  6. 遍历新创建的层级列表,从地图中找到该列表上的相应节点并打印出来

【问题讨论】:

  • @AurA 抱歉,我浏览了你的链接,但它没有建议在 BFS 中遍历时如何存储每个节点的级别,这是我的问题..
  • @AurA 在我看来不像是复制品。 OP 没有询问本地 BFS。考虑“我能够使用 BFS 进行遍历”。
  • 节点 5 重复,是故意的吗?
  • @PhamTrung No.. 错误地添加了..

标签: java algorithm tree


【解决方案1】:

树遍历将是:

7 - 5 - 7 - 6 - 7 - 5 - 2 - 5 - 3 - 5 - 3 - 5 - 7 -6 - 1 - 6 - 4

逻辑是。

总是选择左边的孩子 如果你不能选择一个左孩子,那就选一个右孩子 如果你不能选择任何孩子,去父母那里

在打印方面,跟踪您访问过的节点,如果您访问过它们,则不要打印它们,这样您就不会打印“回溯”

您的节点(伪代码)应如下所示:

Node {
   Node *parent;
   Node *child_left;
   Node *child_right;
   Boolean visited;
   int level;
}

每个节点都应该有一个父节点(根节点除外),并且可以选择有子节点。一旦你遍历它,它就会设置为 true。

当您下降一个级别(即访问一个孩子)时,您应该增加一个 global_level 变量。当你回去(即访问父母)时,你应该减少它。

就将它们存储在列表中而言,您可以只拥有一个全局列表,如果它已经被访问过,就不要推送它。

【讨论】:

    【解决方案2】:

    使用 BFS 遍历。

    有 2 个计数 - 一个是当前级别中剩余的节点数(从 1 开始)和下一级别中剩余的节点数(从 0 开始)。

    每当您处理一个节点时,减少当前级别计数,并为添加到队列中的每个子节点增加下一个级别计数。

    如果当前级别计数为 0,则开始一个新列表。将当前关卡计数设置为下一个关卡计数,并将当前关卡计数设置为0。

    以你的树为例:

    Current level count = 1
    Next level count = 0
    
    Queue: 7
    Dequeue 7, enqueue 5 and 6.
    
    Current list: [7]
    
    Current level count = 1 - 1 = 0
    Next level count = 0 + 2 = 2
    
    Current level count == 0, so
    Current level count = Next level count = 2
    Next level count = 0
    
    Finished with [7], starting a new list
    
    
    Queue: 5, 6
    Dequeue 5, enqueue 2 and 3.
    
    Current list: [5]
    
    Current level count = 2 - 1 = 1
    Next level count = 0 + 2 = 2
    
    
    Queue: 6, 2, 3
    Dequeue 6, enqueue 1 and 4.
    
    Current list: [5, 6]
    ...
    

    【讨论】:

      【解决方案3】:

      假设树中的所有节点都是从 1 到 n,我们可以使用两个数组来存储节点的级别。

      int [] parent = new int[n + 1];//To store the direct parent of the current node
      int [] level = new int[n + 1];//To store the level of the current node
      

      从 root 的级别 0 开始,索引 7 的值为 level[7] = 0;它的两个孩子 5 和 6 将拥有parent[5] = 7 and parent[6] = 7;同样,level[5] = level[parent[5]] + 1level[6] = level[parent[6]] + 1

      通过这些步骤,您可以通过 BFS 填充 parentlevel 数组来逐步构建树结构。

      伪代码

      int [] parent = new int[n + 1];
      int [] level = new int[n + 1];
      Queue q = new Queue();
      level[root.index] = 0;
      q.add(root);
      while(!q.isEmpty()){
          Node node = q.dequeue();
          parent[node.left.index] = node.index;
          parent[node.right.index] = node.index;
          level[node.left.index] = level[parent[node.left.index]] + 1;
          level[node.right.index] = level[parent[node.right.index]] + 1;
          q.add(node.left);
          q.add(node.right);
      
      }
      

      【讨论】:

        【解决方案4】:

        这是一种无需对树节点结构或其他任何东西进行任何更改的方法。

        1. 在读取 BFS 队列时保持levelcounter = 0 的当前级别

        2. 还保留指向队列中下一级节点的下一级节点的指针。

        3. 初始nextlevel = null

        4. 当新的子节点加入队列时,检查下一级指针是否不为空,如果为空则设置为当前子节点指针。

        5. 如果 nextlevel 等于最近删除子节点的指针,则递增 levelcounter 并设置 nextlevel = null

        levelcounter 表示的级别是您在树中的节点级别。

        【讨论】:

          【解决方案5】:

          作为使用 BFS 遍历树并将元素存储在 Q 中的一部分。 在每个级别中,您可以在添加下一级元素之前检查 Q 中有多少元素。

          Queue<Node> q = new LinkedList<>();
          q.offer(head);
          while (!q.isEmpty()){
              int levelSize = q.size();
              for (int i=0; i<levelSize; i++){
                  Node n = q.poll();
                  System.out.print(n.val);
                  if (n.left!=null) q.offer(n.left);
                  if (n.right!=null) q.offer(n.right);
              }
              System.out.println("");
          }
          

          【讨论】:

            【解决方案6】:

            最简单的方法是一次只做一层 BFS。您无需将元素放入队列,而是将每个级别放入一个列表中并在新列表中生成下一个级别:

            List<Node> level = List.of(root);
            
            while (!level.isEmpty()) {
                System.out.println(level);
                level = level.stream()
                            .flatMap(node -> Stream.of(node.left, node.right))
                            .filter(Objects::nonNull)
                            .collect(Collectors.toList());
            }
            

            请注意,System.out.println(level) 假定 Node.toString() 返回字符串化值。如果您不想这样做,则可以在打印之前将 level 映射到整数列表。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2017-10-22
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-05-30
              • 2016-04-16
              相关资源
              最近更新 更多