Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.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_Algorithm_Search_Graph_Priority Queue - Fatal编程技术网

在Java中查找包含循环的图中一定距离内的所有边

在Java中查找包含循环的图中一定距离内的所有边,java,algorithm,search,graph,priority-queue,Java,Algorithm,Search,Graph,Priority Queue,我有一个由Edge对象连接的Node对象图,需要通过以下方式进行探索: 我得到一个起始边源,需要找到所有其他边对象,以便沿路径传递的边的长度总和不超过最大范围,并在满足条件的每个边执行一些操作 我对这个问题的解决方案是递归地进行分支,在我移动时跟踪移动距离(Edge#getEdgeConnections()返回一个ArrayList,其中包含连接到调用的Edge的所有Edge对象): 现在,我想到的解决方案是做一个不同的搜索模式,在那里我会有一个“边界”边的列表(或地图),并按照增加距离的顺序探

我有一个由
Edge
对象连接的
Node
对象图,需要通过以下方式进行探索:

我得到一个起始
边源
,需要找到所有其他
对象,以便沿路径传递的边的长度总和不超过
最大范围
,并在满足条件的每个
执行一些操作

我对这个问题的解决方案是递归地进行分支,在我移动时跟踪移动距离(
Edge#getEdgeConnections()
返回一个
ArrayList
,其中包含连接到调用的
Edge
的所有
Edge
对象):

现在,我想到的解决方案是做一个不同的搜索模式,在那里我会有一个“边界”边的列表(或地图),并按照增加距离的顺序探索它们(每次探索一条边时都会向这个边界添加新边)

可能会涉及到大量的边,因此我不希望每次都遍历整个列表,以找到距离源最短的边

是否有某种类型的集合能够以这种方式自动保持订单,并且能够有效地添加/删除元素

SortedMap是我要找的吗?在这种情况下,我将如何使用它

编辑:
感谢所有响应者。最后,我使用了一个带有包装类的
PriorityQueue
(有关详细信息和代码,请参见)。

您可以使用对BFS或DFS的修改,其中还为路径的最大长度添加了一个额外规则(除了检查是否访问了所有邻居节点)


我建议你选择DFS,因为它有点接近你目前正在做的事情。您也可以用任何一种方法轻松地“放入”doSomethingToEdge,而不是使用其他数据结构,我建议您调整算法:


您已经实现了某种方法来遍历图形。如果您使用某种类型的替换,您可以在到达指定范围并访问了范围内的每条边一次后停止(通过使用您已经实现的isOccupied逻辑)。

注意:写下答案后,我意识到您是在谈论边,但我在节点方面提到的相同示例和相同理论也适用于边。

如果只执行BFS,它将不起作用,因为您会将
节点
标记为过早访问。考虑这个例子

最大范围为20&
d(x,y)
表示
x
y

         A->(10)E->D(10)->(5)F // d(A,E)=d(E,D)=10 & d(D,F)=5

         A->(5)B->(5)C->(5)D->(5)F //d(A,B)=d(B,C)=d(C,D)=d(D,F)=5  
在这种情况下,您将首先到达路径
(a->E->D)
中的D(因为它更接近此路径中的a),然后将
D
标记为已访问。这实际上是错误的,因为将D标记为已访问会阻止您访问
F
,如果您的路径是
(A->B->C->D->F)
,您本可以这样做

因此,为了避免重复并解决此问题,对于要添加的每个节点,还应添加在当前路径中看到的节点列表。这样,您仍然可以访问
F
,因为当您在路径
(A->B->C->D)
中到达
D
时,您将看到它未被访问,因为它没有出现在您的路径中

说到实施,我将给您一个大致的想法:

创建一个包装类

   NodeWrapper{
      Node node;
      List<Node> Parents;
      int pathSum;
   }
NodeWrapper{
节点;
列出家长名单;
int路径和;
}
您的BFS应如下所示:

 { 

   Queue<NodeWrapper> queue = new LinkedList<>();
   Queue.add(new NodeWrapper(sourceNode,new ArrayList<Node>));

   while(!queue.isEmpty()){
         NodeWrapper temp = queue.poll();
         Node presentNode = temp.getNode();
         List<Node> parentsList = temp.getParentsList();
         for all neighbours of presentNode
              if neighbour is not in presentNode && (pathSum +currentEdgeWeight )< max && your conditions
             add currentNode to parent list
             queue.add(new NodeWrapper(neighbour,parentList,(pathSum +currentEdgeWeight)));

   }

 }
{
Queue Queue=new LinkedList();
add(新的NodeWrapper(sourceNode,newarraylist));
而(!queue.isEmpty()){
NodeWrapper temp=queue.poll();
Node presentNode=temp.getNode();
List parentsList=temp.getParentsList();
对于presentNode的所有邻居
如果邻居不在presentNode&(pathSum+CurrentEdgeWight)
您正在寻找的算法是一种改进的算法,它不是搜索从a到B的最短路径,而是搜索所有短于X的最短路径。Dijkstra保证您将按照距离起点的递增顺序访问每个节点,并通过距离起点的最短路径。此外,如果没有负长度边,那么父级关系将永远不会改变——并且可以保证内部
if
将沿着节点的最小路径对每条边执行一次且仅执行一次。但是,由于“比X更近的节点”集仅在末端已知(=最终距离<最大值的节点),因此您可以等待算法完成
doStuffAtBranch
,仅适用于实际通向某个有趣地方的分支

伪代码如下所示:

final HashMap<Node, Double> distances = new HashMap<>();
HashMap<Node, Node> parents = new HashMap<>();
distances.put(start, 0);  // start is at distance 0 from start

PriorityQueue<Vertex> q = new PriorityQueue(allVertices.size(), 
    new Comparator<Vertex>() {
        public int compare(Vertex a, Vertex b) {
            return distances.get(a) - distances.get(b);
        }
});

for (Vertex v : allVertices) {
    q.add(v, distances.contains(v) ? 
        distances.get(v) : Double.POSITIVE_INFINITY);
}

while ( ! q.isEmpty()) {
    Vertex u = q.poll(); // extract closest
    double current = distances.get(u);
    if (current > max) {
        // all nodes that are reachable in < max have been found
        break;
    }
    for (Edge e : u.getEdges()) {
        Vertex v = u.getNeighbor(e);
        double alt = current + e.length();
        if (alt < distances.get(v)) {
            q.remove(v);       // remove before updating distance
            distances.put(v, alt);
            parents.put(v, u); // v will now be reached via u
            q.add(v);          // re-add with updated distance
            // if there are no negative-weight edges, e will never be re-visited
        }
    }
}
final HashMap distance=new HashMap();
HashMap parents=newhashmap();
距离。放置(开始,0);//起点距离起点0
PriorityQueue q=新建PriorityQueue(allVertices.size(),
新比较器(){
公共整数比较(顶点a、顶点b){
返回距离。get(a)-距离。get(b);
}
});
对于(顶点v:所有顶点){
q、 添加(v,距离。是否包含(v)?
距离。get(v):双正_无穷大);
}
而(!q.isEmpty()){
顶点u=q.poll();//提取最近的
双电流=距离。获取(u);
如果(当前>最大值){
//已找到 { 

   Queue<NodeWrapper> queue = new LinkedList<>();
   Queue.add(new NodeWrapper(sourceNode,new ArrayList<Node>));

   while(!queue.isEmpty()){
         NodeWrapper temp = queue.poll();
         Node presentNode = temp.getNode();
         List<Node> parentsList = temp.getParentsList();
         for all neighbours of presentNode
              if neighbour is not in presentNode && (pathSum +currentEdgeWeight )< max && your conditions
             add currentNode to parent list
             queue.add(new NodeWrapper(neighbour,parentList,(pathSum +currentEdgeWeight)));

   }

 }
final HashMap<Node, Double> distances = new HashMap<>();
HashMap<Node, Node> parents = new HashMap<>();
distances.put(start, 0);  // start is at distance 0 from start

PriorityQueue<Vertex> q = new PriorityQueue(allVertices.size(), 
    new Comparator<Vertex>() {
        public int compare(Vertex a, Vertex b) {
            return distances.get(a) - distances.get(b);
        }
});

for (Vertex v : allVertices) {
    q.add(v, distances.contains(v) ? 
        distances.get(v) : Double.POSITIVE_INFINITY);
}

while ( ! q.isEmpty()) {
    Vertex u = q.poll(); // extract closest
    double current = distances.get(u);
    if (current > max) {
        // all nodes that are reachable in < max have been found
        break;
    }
    for (Edge e : u.getEdges()) {
        Vertex v = u.getNeighbor(e);
        double alt = current + e.length();
        if (alt < distances.get(v)) {
            q.remove(v);       // remove before updating distance
            distances.put(v, alt);
            parents.put(v, u); // v will now be reached via u
            q.add(v);          // re-add with updated distance
            // if there are no negative-weight edges, e will never be re-visited
        }
    }
}
public ArrayList<Edge> uniqueEdgesWithinRange(double range) {
    ArrayList<Edge> edgeList = new ArrayList<>();
    PriorityQueue<ComparableEdge> frontier = new PriorityQueue<>();
    frontier.add(new ComparableEdge(0.0, this));

    while(!frontier.isEmpty()) {
        ComparableEdge cEdge = frontier.poll();

        edgeList.add(cEdge.edge);

        if (cEdge.distance < range) {
            for (Edge connection : cEdge.edge.getEdgeConnections()) {
                if (!edgeList.contains(connection)) {
                    frontier.add(new ComparableEdge(cEdge.distance + connection.getLength(), connection));
                }
            }
        }
    }

    return edgeList;
}

private class ComparableEdge implements Comparable<ComparableEdge> {
    private double distance; // Distance from closest point on source to furthest point on edge
    private Edge edge;

    private ComparableEdge(double distance, Edge edge) {
        this.distance = distance;
        this.edge = edge;
    }

    @Override
    public int compareTo(ComparableEdge another) {
        return Double.compare(distance, another.distance);
    }
}
public List<Integer> findMinDistantNodesUsingBF(int[][] graph, int startNode, int distance) {
    int len = graph.length;
    boolean[] processed = new boolean[len];
    int[] distanceArr = new int[len];
    LinkedList<Integer> queue = new LinkedList<Integer>();
    List<Integer> result = new ArrayList<Integer>();
    queue.add(startNode);
    processed[startNode] = true;
    distanceArr[startNode] = 0;
    while (!queue.isEmpty()) {
        int node = queue.remove();
        for (int i = 0; i < len; i++) {
            if (graph[node][i] == 1 && !processed[i]) {
                if (distanceArr[node] == distance - 1) {
                    result.add(i);
                } else {
                    queue.add(i);
                    distanceArr[i] = distanceArr[node] + 1;
                }
                processed[i] = true;
            }
        }
    }

    return result;
}
// Finds all nodes that are maximum x distance away from given node.
public Set<Integer> findMaxDistantNodesRecurse(int[][] graph, int startNode, int distance) {
    int len = graph.length;
    Set<Integer> set = new HashSet<Integer>();

    for (int j = 0; j < len; j++) {
        if (startNode == j)
            continue;
        if (graph[startNode][j] == 1) {
            set.add(j);
            if (distance > 1)
                set.addAll(findMaxDistantNodesRecurse(graph, j, distance - 1));

        }
    }

    return set;
}