【问题标题】:Breadth First Search - Java广度优先搜索 - Java
【发布时间】:2026-01-01 12:15:02
【问题描述】:

作为一个学校练习,我在 Java 中实现了广度优先搜索。我已经实现了几乎所有的东西,但问题是我的搜索不起作用,我找不到问题:( 所以我请你给我建议,给我一些关于最终问题可能出在哪里的指导方针。

public ArrayList<SearchNode> search(Problem p) {
        // The frontier is a queue of expanded SearchNodes not processed yet
        frontier = new NodeQueue();
        /// The explored set is a set of nodes that have been processed 
        explored = new HashSet<SearchNode>();
        // The start state is given
        GridPos startState = (GridPos) p.getInitialState();
        // Initialize the frontier with the start state  
        frontier.addNodeToFront(new SearchNode(startState));

        // Path will be empty until we find the goal.
        path = new ArrayList<SearchNode>();

        // The start NODE

        SearchNode node = new SearchNode(startState); 

        // Check if startState = GoalState??
        if(p.isGoalState(startState)){
           path.add(new SearchNode(startState)); 
           return path; 
        }


        do {  

          node = frontier.removeFirst();
          explored.add(node); 

          ArrayList reachable = new ArrayList<GridPos>();
          reachable = p.getReachableStatesFrom(node.getState()); 

          SearchNode child; 

          for(int i = 0; i< reachable.size(); i++){

              child = new SearchNode((GridPos)reachable.get(i)); 

              if(!(explored.contains(child) || frontier.contains(child))){
                  if(p.isGoalState(child.getState())){
                      path = child.getPathFromRoot() ;  
                      return path; 
                  }
                  frontier.addNodeToFront(child); 
              }

          }
        }while(!frontier.isEmpty());


        return path;
    }

谢谢

【问题讨论】:

  • 怎么不工作了?准确。
  • 它似乎在探索“错误”的节点和路径。
  • 您有很多方法没有向我们展示。您似乎正在从两个不同的数组/列表中提取节点并将可达节点插入到其中一个。你的情况也很奇怪,你应该只检查explored 列表,在一个经典的实现中。基本思想是:从列表的开头提取第一个节点,将其所有邻居添加到同一列表的末尾。当列表为空或将目标节点添加到该列表时停止。
  • 这只是一个假设,但是 SearchNode 的 hashCode 和 equals 方法看起来如何? explore.contains(child) 可以同时使用这两种方法来查找 SearchNode,但可能会失败。
  • 我将addNodeToBack 恢复为addNodeToFront - 因为这是这个答案中的一个重要问题,正如 Alex Lynch 在他的回答中提到的那样。请不要更改它,因为它可能会帮助将来遇到类似问题并且在阅读编辑后的问题后无法理解问题所在的读者。

标签: java algorithm search breadth-first-search


【解决方案1】:

为了实现广度优先搜索,您应该使用队列。这个过程可能会变得非常复杂。所以,最好保持简单。您应该将节点的子节点推送到队列(从左到右),然后访问该节点(打印数据)。然后,你应该从队列中删除节点。您应该继续此过程,直到队列变空。你可以在这里看到我的 BFS 实现:https://github.com/m-vahidalizadeh/foundations/blob/master/src/algorithms/TreeTraverse.java

【讨论】:

    【解决方案2】:
    frontier.addNodeToFront(child);
    

    假设您的其余代码(getReachableStatesFrom() 等)是正确的,将元素添加到队列的前面将导致您的代码作为深度优先搜索执行。

    【讨论】:

    • 是的,你是对的。我犯的愚蠢错误。在更改它以将节点添加到后面之后,它似乎“几乎可以工作”:D
    • @user1285737 如果您可以确定您的代码可能存在问题的另一个地方,请随时打开另一个问题 :) 如果您认为我已经正确回答了这个问题,接受我的回答是首选方式的感谢。祝你好运!