简体   繁体   English

寻找两点之间的最短路径(bfs)

[英]Finding the shortest path between two points(bfs)

I have a task. 我有任务 I need find the shortest path between two points. 我需要找到两点之间的最短路径。 For this i use breadth first search algorithm. 为此,我使用广度优先搜索算法。 I create class Graph which has amount of vertices, and adjacency list. 我创建了具有大量顶点和邻接表的Graph类。 Here is my code: 这是我的代码:

class Graph
{
    private int V;   
    private LinkedList<Integer> adj[]; //Adjacency Lists

    // Constructor
    Graph(int v)
    {
        V = v;
        adj = new LinkedList[v];
        for (int i=0; i<v; ++i)
            adj[i] = new LinkedList();
    }

    // Function to add an edge into the graph
    void addEdge(int v,int w)
    {
        adj[v].add(w);
    }

    // prints BFS traversal from a given source s
    void BFS(int s)
    {
        // Mark all the vertices as not visited(By default
        // set as false)
        boolean visited[] = new boolean[V];

        // Create a queue for BFS
        LinkedList<Integer> queue = new LinkedList<Integer>();

        // Mark the current node as visited and enqueue it
        visited[s]=true;
        queue.add(s);

        while (queue.size() != 0)
        {
            // Dequeue a vertex from queue and print it
            s = queue.poll();
            System.out.print(s+" ");

            // Get all adjacent vertices of the dequeued vertex s
            // If a adjacent has not been visited, then mark it
            // visited and enqueue it
            Iterator<Integer> i = adj[s].listIterator();
            while (i.hasNext())
            {
                int n = i.next();
                if (!visited[n])
                {
                    visited[n] = true;
                    queue.add(n);
                }
            }
        }
    }

    // Driver method to
    public static void main(String args[])
    {
       Graph g = new Graph(8);
        g.addEdge(0, 5);
        g.addEdge(0, 7);
        g.addEdge(1, 5);
        g.addEdge(1, 4);
        g.addEdge(1, 2);
        g.addEdge(2, 1);
        g.addEdge(2, 4);
        g.addEdge(2, 3);
        g.addEdge(3, 4);
        g.addEdge(3, 2);
        g.addEdge(4, 5);
        g.addEdge(4, 1);
        g.addEdge(4, 2);
        g.addEdge(4, 3);
        g.addEdge(5, 0);
        g.addEdge(5, 1);
        g.addEdge(5, 4);
        g.addEdge(6, 7);
        g.addEdge(7,6);
        g.addEdge(7,0);
        g.BFS(2);

        g.BFS(2);
    }
}

But i need function that print shortest path from the start index to the end. 但是我需要打印从开始索引到结束的最短路径的函数。 How i can organize it. 我如何组织它。 Please, help me. 请帮我。

I used a recursion, where all answers will be stored in the arrayList. 我使用了递归,其中所有答案都将存储在arrayList中。

getPath(int from, int to, int current, String answer) getPath(int from,int to,int current,字符串答案)

  • from - a starting point 从-起点
  • to - ending point 至终点
  • current - just a current value 当前-只是一个当前值
  • answer - the whole path 答案-整个路径

Just add this code to the Graph class. 只需将此代码添加到Graph类。

public ArrayList<String> answers = new ArrayList<String>();

public void printShortAnswer() {
    String realAnswer = "";
    for (String answer : answers) {
        if (realAnswer == "" || realAnswer.length() > answer.length()) {
            realAnswer = answer;
        }
    }
    System.err.println("The shortest path is: " + realAnswer);
}

//store all answers in answers
public boolean getPath(int from, int to, int current, String answer) {
    boolean visited[] = new boolean[V];
    visited[from] = true;
    visited[current] = true;

    if (current == to) {
         answers.add(answer);
        return true;
    }

    Iterator<Integer> i = adj[current].listIterator();
    while (i.hasNext())
    {
        int n = i.next();
        if (!visited[n])
        {
            visited[n] = true;
            getPath(from, to, n, answer + " " + n);
        }
    }
    return false;
}

To run it, just use this setup 要运行它,只需使用此设置

  Graph g = new Graph(12);
    g.addEdge(0, 1);
    g.addEdge(0, 2);

    //set 1
    g.addEdge(1, 3);
    g.addEdge(3, 4);
    g.addEdge(4, 5);

    //set 2
    g.addEdge(2, 8);
    g.addEdge(8, 9);
    g.addEdge(9, 11);
    g.addEdge(11, 5);

    g.addEdge(0, 5);
    //g.BFS(0);

    int startPoint = 0;
    g.getPath(startPoint, 5, startPoint, startPoint + " ");
    g.printShortAnswer();

And don't forget to import ArrayList. 并且不要忘记导入ArrayList。

import java.util.ArrayList;

The output will be: 输出将是:

  • 0 1 3 4 5 0 1 3 4 5
  • 0 2 8 9 11 5 0 2 8 9 11 5
  • 0 5 0 5
  • The shortest path is: 0 5 最短的路径是:0 5

Breadth-first search is appropriate here, because when you visit the destination node for the first time, you will do so via the shortest path. 广度优先搜索在这里是合适的,因为当您第一次访问目标节点时,将通过最短路径进行搜索。 This works, because all edges have the same weight, 1. If edges can have different weights, the path with the fewest edges isn't necessarily the shortest one and you will need other algorithms, for example Dijkstra's . 之所以可行,是因为所有边缘的权重均相同。1.如果边缘的权重不同,则边缘最少的路径不一定是最短的路径,并且您将需要其他算法,例如Dijkstra的

You code doesn't check whether you have reached the destination; 您的代码不会检查您是否已到达目的地; it just visits all nodes in breadh-first order. 它只是按照广度优先顺序访问所有节点。

You also cannot print the nodes as you go, because when you visit an adjacent unvisited node, you don't know yet whether it is part of the shortest path or whether you are going in the wrong direction. 您也不能随便打印节点,因为当您访问相邻的未访问节点时,您仍然不知道它是否是最短路径的一部分,或者您走错了方向。

A solution to this is to store the previous vertex, ie the one you have come from, for each vertex. 一种解决方案是为每个顶点存储先前的顶点,即您来自的顶点。 For example if you start your search at vertex 0, you will visit the adjacent vertices 5 and 7. Therefore, the previous vertex for both 5 and 7 is 0. 例如,如果您从顶点0开始搜索,您将访问相邻的顶点5和7。因此,5和7的先前顶点均为0。

This information can do double duty: If you use −1 to mean "no vertex", a previous vertex of −1 means that the vertex hasn't been visited yet. 此信息可以起到双重作用:如果使用-1表示“无顶点”,则-1的前一个顶点表示尚未访问该顶点。

When you visit the destination, just retrace your steps via the information of previous nodes until you reach the original vertex. 当您访问目的地时,只需通过先前节点的信息来追溯您的步骤,直到到达原始顶点。 This list will be the path from the destination to the origin. 此列表将是从目的地到起点的路径。

Here's the implementation in (my poor) Java: 这是(我可怜的)Java中的实现:

import java.util.LinkedList;
import java.util.Iterator;

class Graph
{
    private int V;   
    private LinkedList<Integer> adj[];

    Graph(int v)
    {
        V = v;
        adj = new LinkedList[v];

        for (int i = 0; i < v; i++) {
            adj[i] = new LinkedList();
        }
    }

    void addEdge(int v, int w)
    {
        adj[v].add(w);
    }

    LinkedList shortest(int from, int to)
    {
        LinkedList<Integer> queue = new LinkedList<Integer>();
        LinkedList<Integer> res = new LinkedList<Integer>();

        int prev[] = new int[V];

        if (from == to) return res;
        queue.add(from);

        for (int i = 0; i < V; i++) {
            prev[i] = -1;
        }        

        while (queue.size() != 0) {
            int curr = queue.poll();
            Iterator<Integer> i = adj[curr].listIterator();

            while (i.hasNext()) {
                int n = i.next();

                if (prev[n] == -1) {                // unvisited?
                    prev[n] = curr;                 // store previous vertex

                    if (n == to) {                  // we're finally there!
                        while (n != from) {         // build result list ...
                            res.addFirst(n);
                            n = prev[n];
                        }

                        return res;                 // ... and return it
                    }                    

                    queue.add(n);
                }
            }
        }

        return res;
    }

    public static void main(String args[])
    {
        Graph g = new Graph(9);

        g.addEdge(0, 5);
        g.addEdge(0, 7);
        g.addEdge(1, 5);
        g.addEdge(1, 4);
        g.addEdge(1, 2);
        g.addEdge(2, 1);
        g.addEdge(2, 4);
        g.addEdge(2, 3);
        g.addEdge(3, 4);
        g.addEdge(3, 2);
        g.addEdge(4, 5);
        g.addEdge(4, 1);
        g.addEdge(4, 2);
        g.addEdge(4, 3);
        g.addEdge(5, 0);
        g.addEdge(5, 1);
        g.addEdge(5, 4);
        g.addEdge(6, 7);
        g.addEdge(7,6);
        g.addEdge(7,0);

        for (int a = 0; a < 9; a++) {
            System.out.print("--- ");
            System.out.println(a);

            for (int b = 0; b < 9; b++) {
                System.out.println(g.shortest(a, b));                
            }
        }    
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM