Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中,如何将这种广度优先的搜索转换为静态方法?_Java_Python_Search_Breadth First Search - Fatal编程技术网

在Java中,如何将这种广度优先的搜索转换为静态方法?

在Java中,如何将这种广度优先的搜索转换为静态方法?,java,python,search,breadth-first-search,Java,Python,Search,Breadth First Search,我用Python编写这个静态方法是为了进行广度优先搜索。但是,我主要使用Java,我想了解数据结构如何转换为Java,给定泛型等。我的代码是: def bfs(graph, start_vertex, target_value): path = [start_vertex] #a list that contains start_vertex vertex_and_path = [start_vertex, path] #a list that contains start_vertex

我用Python编写这个静态方法是为了进行广度优先搜索。但是,我主要使用Java,我想了解数据结构如何转换为Java,给定泛型等。我的代码是:

def bfs(graph, start_vertex, target_value):
  path = [start_vertex] #a list that contains start_vertex
  vertex_and_path = [start_vertex, path] #a list that contains start_vertex and path
  bfs_queue = [vertex_and_path]
  visited = set() #visited defined as an empty set

  while bfs_queue: #while the queue is not empty
    current_vertex, path = bfs_queue.pop(0) #removes element from queue and sets both equal to that first element
    visited.add(current_vertex) #adds current vertex to visited list

    for neighbor in graph[current_vertex]: #looks at all neighboring vertices
      if neighbor not in visited: #if neighbor is not in visited list
        if neighbor is target_value: #if it's the target value
          return path + [neighbor] #returns path with neighbor appended
        else:
          bfs_queue.append([neighbor, path + [neighbor]]) #recursive call with path that has neighbor appended
我将在上面使用的图表是:

myGraph = { //I'm not sure how to structure this in Java
    'lava': set(['sharks', 'piranhas']),
    'sharks': set(['lava', 'bees', 'lasers']),
    'piranhas': set(['lava', 'crocodiles']),
    'bees': set(['sharks']),
    'lasers': set(['sharks', 'crocodiles']),
    'crocodiles': set(['piranhas', 'lasers'])
  }
我可以这样称呼它

public static void main(String[] args){
    System.out.println(bfs(myGraph, "crocodiles", "bees"));
}
到目前为止,我拥有以下Java:

    public class BreadthFirstSearch{

    ///NOT DONE YET
    public static ArrayList<String> BFS(Map<String, String[]> graph, String start, String target) {
            List<String> path = new ArrayList<>();
            path.add(start);
            List<String> vertexAndPath = new ArrayList<>();
            vertexAndPath.add(start);
            vertexAndPath.add(path.get(0));
            ArrayList<String> queue = new ArrayList<>();
            queue.add(vertexAndPath.get(0));
            queue.add(vertexAndPath.get(1));
            Set<String> visited = new HashSet<String>();
            while(!queue.isEmpty()) {
                String currentVertex = queue.remove(0);
                String curVerValue = currentVertex;
                path.add(currentVertex);
                .
                .
                .
            }
        }
}
公共类广域优先搜索{
///还没做完
公共静态ArrayList BFS(映射图、字符串开始、字符串目标){
列表路径=新的ArrayList();
添加路径(开始);
List vertexAndPath=new ArrayList();
添加(开始);
add(path.get(0));
ArrayList队列=新建ArrayList();
add(vertexAndPath.get(0));
add(vertexAndPath.get(1));
Set visted=新HashSet();
而(!queue.isEmpty()){
字符串currentVertex=queue.remove(0);
字符串CurveValue=currentVertex;
添加(currentVertex);
.
.
.
}
}
}

您需要创建一个单独的类来保存图形的节点。这些节点不能是静态的,因为它们都有唯一的顶点。从那里看,其余的情况非常相似

public class Node {
    public String name;
    public ArrayList<Node> vertices;
    public void addEdge(Node node) {
        edges.add(node);
    }
}
公共类节点{
公共字符串名称;
公共阵列列表顶点;
公共无效添加(节点){
添加(节点);
}
}

翻译工作做得很好。让我提供我的代码,然后解释一下:

import java.util.*;

class BreadthFirstSearch {
    public static ArrayList<String> BFS(
        Map<String, String[]> graph, String start, String target
    ) {
        Map<String, String> visited = new HashMap<>();
        visited.put(start, null);
        ArrayDeque<String> deque = new ArrayDeque<>();
        deque.offer(start);

        while (!deque.isEmpty()) {
            String curr = deque.poll();

            if (curr.equals(target)) {
                ArrayList<String> path = new ArrayList<>();
                path.add(curr);

                while (visited.get(curr) != null) {
                    curr = visited.get(curr);
                    path.add(curr);
                }

                Collections.reverse(path);
                return path;
            }

            for (String neighbor : graph.get(curr)) {
                if (!visited.containsKey(neighbor)) {
                    visited.put(neighbor, curr);
                    deque.offer(neighbor);
                }
            }
        }

        return null;
    }

    public static void main(String[] args) {
        Map<String, String[]> myGraph = new HashMap<>();
        myGraph.put(
            "lava", new String[] {"sharks", "piranhas"}
        );
        myGraph.put(
            "sharks", new String[] {"lava", "bees", "lasers"}
        );
        myGraph.put(
            "piranhas", new String[] {"lava", "crocodiles"}
        );
        myGraph.put(
            "bees", new String[] {"sharks"}
        );
        myGraph.put(
            "lasers", new String[] {"sharks", "crocodiles"}
        );
        myGraph.put(
            "crocodiles", new String[] {"piranhas", "lasers"}
        );
        System.out.println(BFS(myGraph, "crocodiles", "bees"));
        System.out.println(BFS(myGraph, "crocodiles", "crocodiles"));
        System.out.println(BFS(myGraph, "crocodiles", "zebras"));
    }
}

解释 我做出的设计决定是避免在图中的每个节点上复制
路径
数组列表,而使用
访问的
散列将节点存储在
childNode=>parentNode
对中。这样,一旦我找到了目标节点,我就可以一次返回创建路径的步骤,而不是为每个节点创建一条路径,因为大多数节点最终都不会通向任何地方。这在空间和时间上更有效;Python使用
[]+[]
O(n)列表串联运算符很容易破坏时间复杂性

使用
child=>parent
访问的HashMap也比用Java编写代码更简单,因为Java没有轻量级的
/
元组
/
结构
,可以方便地将不同类型存储为队列中的节点。要在Python中将2元素列表传递到队列中,您必须编写自己的
Pair
类,使用两个arrayques,或者避免泛型并使用强制转换,所有这些都很难看(尤其是最后一个,这也是不安全的)

我在代码中注意到的另一个问题是使用ArrayList作为队列。列表前面的插入和删除是一个O(n)操作,因为列表中的所有元素必须在底层数组中向前或向后移动,以保持顺序。Java中的最佳队列结构是,与集合不同,它在两端提供O(1)添加和删除,并且不是线程安全的

类似地,在Python中,您会发现使用的性能最好,它为您的所有排队需求提供了快速的
popleft
操作。此外,在Python实现中,散列中的每个键都指向一个
,这是可以的,但在列表中似乎是不必要的结构(您已经切换到Java中的基本数组)。如果您不操纵图形,只在邻居上迭代,这似乎是理想的

请注意,此代码还假定每个节点在表示图形的哈希中都有一个键,就像您的输入一样。如果您计划在节点哈希中可能没有键的情况下输入图形,则需要确保
graph.get(curr)
使用
containsKey
检查进行包装,以避免崩溃


另一个值得一提的假设是:确保您的图形不包含
null
s,因为访问的
散列依赖于
null
来指示子对象没有父对象,并且是搜索的开始。

这也可能有助于发布您希望的搜索结果。我对python不是非常精通,所以我想我知道它在做什么,但我不是100%确定。@CodyKnapp它应该是一个类似于python输出的路径的表示:
['鳄鱼'、'激光'、'鲨鱼'、'蜜蜂']
无法以几乎相同的方式复制
myGraph
结构??