简体   繁体   English

使用邻接表BFS遍历图中所有路径

[英]BFS traversal of all paths in graph using adjacency list

I am currently trying to traverse all paths from source to destination in a graph which uses adjacency matrix.我目前正在尝试在使用邻接矩阵的图中遍历从源到目标的所有路径。 I have been trying to do it in BFS way.Thanks for the help.我一直在尝试以 BFS 方式进行。感谢您的帮助。 I am getting only one path.我只有一条路。 How do I get to print other paths as well ?我如何才能打印其他路径?

public class AllPossiblePaths {
    static int v;
    static ArrayList<Integer> adj[];

    public AllPossiblePaths(int v) {
        this.v = v;
        adj = new ArrayList[v];
        for (int i = 0; i < v; i++) {
            adj[i] = new ArrayList<>();
        }
    }

    // add edge from u to v
    public static void addEdge(int u, int v) {
        adj[u].add(v);
    }

    public static void findpaths(int source, int destination) {
        LinkedList<ArrayList<Integer>> q = new LinkedList<>();
        boolean visited[] = new boolean[v];

        LinkedList<Integer> queue = new LinkedList<Integer>();

        queue.add(source);
        visited[source] = true;
        ArrayList<Integer> localPath = new ArrayList<>();
        while (!queue.isEmpty()) {
            // Dequeue a vertex from queue and print it
            int src = queue.poll();
            if (!localPath.contains(src)) {
                localPath.add(src);
            }
            if (src == destination) {
                System.out.println(localPath);
                localPath.remove(localPath.size() - 1);
                visited[src] = false;
            }

            Iterator<Integer> i = adj[src].listIterator();
            while (i.hasNext()) {
                int n = i.next();
                if (!visited[n]) {
                    queue.add(n);
                }
            }
        }
    }
}

Using the following class you can run a BFS to find a single path ( findPath ) or find multiple paths ( findAllPaths ).使用以下类,您可以运行 BFS 来查找单个路径 ( findPath ) 或查找多个路径 ( findAllPaths )。 See comments:看评论:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

public class AllPossiblePaths {

    private  boolean[] visited;
    //keep track of nodes already included in a path
    private  boolean[] includedInPath;
    private LinkedList<Integer> queue;
    private int numberOfNodes;
    private List<Integer>[] adj;
    //to find a path you need to store the path that lead to it
    private List<Integer>[] pathToNode;

    public AllPossiblePaths(int numberOfNodes) {

        this.numberOfNodes = numberOfNodes;
        adj = new ArrayList[numberOfNodes];
        pathToNode = new ArrayList[numberOfNodes];

        for (int i = 0; i < numberOfNodes; i++) {
            adj[i] = new ArrayList<>();
        }
    }

    // add edge from u to v
    public AllPossiblePaths addEdge(int from, int to) {
        adj[from].add(to);
        //unless unidirectional: //if a is connected to b
        //than b should be connected to a
        adj[to].add(from);
        return this; //makes it convenient to add multiple edges
    }

    public void findPath(int source, int destination) {

        System.out.println("------------Single path search---------------");
        initializeSearch(source);

        while (!queue.isEmpty()) {
            // Dequeue a vertex from queue and print it
            int src = queue.poll();
            visited[src] = true;

            if (src == destination) {
                System.out.println("Path from "+source+" to "
                        + destination+ " :- "+ pathToNode[src]);
                break; //exit loop if target found
            }

            Iterator<Integer> i = adj[src].listIterator();
            while (i.hasNext()) {
                int n = i.next();
                if (! visited[n] && ! queue.contains(n)) {
                    queue.add(n);
                    pathToNode[n].addAll(pathToNode[src]);
                    pathToNode[n].add(src);
                }
            }
        }
    }

    public void findAllpaths(int source, int destination) {

        System.out.println("-----------Multiple path search--------------");
        includedInPath = new boolean[numberOfNodes];
        initializeSearch(source);
        int pathCounter = 0;

        while(! allVisited() && !queue.isEmpty()) {

            while (!queue.isEmpty()) {
                // Dequeue a vertex from queue and print it
                int src = queue.poll();
                visited[src] = true;

                if (src == destination) {

                    System.out.println("Path " + ++pathCounter + " from "+source+" to "
                            + destination+ " :- "+ pathToNode[src]);
                    //mark nodes that are included in the path, so they will not be included
                    //in any other path
                    for(int i=1; i < pathToNode[src].size(); i++) {
                        includedInPath[pathToNode[src].get(i)] = true;
                    }
                    initializeSearch(source); //initialize before restarting
                    break; //exit loop if target found
                }

                Iterator<Integer> i = adj[src].listIterator();
                while (i.hasNext()) {
                    int n = i.next();
                    if (! visited[n] && ! queue.contains(n)
                            && ! includedInPath[n] /*ignore nodes already in a path*/) {
                        queue.add(n);
                        pathToNode[n].addAll(pathToNode[src]);
                        pathToNode[n].add(src);
                    }
                }
            }
        }
    }

    private void initializeSearch(int source) {

        queue = new LinkedList<>();
        queue.add(source);
        visited = new boolean[numberOfNodes];
        for (int i = 0; i < numberOfNodes; i++) {
            pathToNode[i]= new ArrayList<>();
        }
    }

    private boolean allVisited() {

        for( boolean b : visited) {
            if(! b ) return false; 
        }
        return true;
    }
}

For testing it, consider this graph:为了测试它,请考虑以下图表:

在此处输入图片说明

Run test:运行测试:

public static void main(String[] args){

    AllPossiblePaths app = new AllPossiblePaths(6);
    app.addEdge(0, 4)
    .addEdge(0, 1)
    .addEdge(1, 2)
    .addEdge(1, 4)
    .addEdge(4, 3)
    .addEdge(2, 3)
    .addEdge(2, 5)
    .addEdge(3, 5);

    app.findPath(0,5);
    app.findPath(5,0);
    app.findAllpaths(0,5);
}

output:输出:

在此处输入图片说明

Apparently it is impossible to retrieve all paths from a given source to a given terminal via Breadth-First search.显然,不可能通过广度优先搜索检索从给定源到给定终端的所有路径。 Consider the following class of graphs.考虑以下类别的图。

For any nonnegative integer n , let对于任何非负整数n ,令

V := {v_1,...,v2_n}                             // inner vertices
     union
     {s, t},                                    // source and terminal
E := { {v_i,v+2,} : i < 2n-2 }                  // horizontal edges
     union
     { {v_i,v_i+3} : i < 2n-3, i is odd }       // cross edges from top to bottom
     union
     { {v_i,v_i+3} : i < 2n-3, i is even }      // cross edges from bottom to top
     union
     { {s,v_1}, {s,v_2}, {t,v_2n-1}, {t,v_2n} } // source and terminal

Informally, the graph consists out of two rows of vertices with n columns each, to the left there is a source node and to the right there is a terminal node.非正式地,该图由两行顶点组成,每行有n列,左侧有一个源节点,右侧有一个终端节点。 For each path from s to t , you can choose for each column to stay in the current row or to switch to the other row.对于从st每条路径,您可以选择让每一列留在当前行或切换到另一行。

In total, there are 2^n different paths from s to t , as for each column there are two possibilities to chose the row.总的来说,从st2^n不同的路径,对于每一列,有两种选择行的可能性。

On the other hand, Breadth-First search yields a runtime bound which is polynomial in the encoding length of the graph;另一方面,广度优先搜索产生一个运行时边界,它是图编码长度的多项式; this means that Breadth-first search, in general, cannot generate all possible paths from a given source to a given terminal.这意味着广度优先搜索通常无法生成从给定源到给定终端的所有可能路径。 Furthermore, if the graph contains a cycle, the number of paths might be inifinite via repetition of the cycle.此外,如果图形包含一个循环,则通过循环的重复,路径的数量可能是无限的。

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

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