我目前正试图在使用邻接矩阵的图中遍历从源到目的地的所有路径。我一直试图用BFS方式做到这一点。谢谢你的帮助。我只得到一条路。我如何打印其他路径?
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);
}
}
}
}
}
答案 0 :(得分:2)
使用以下类,您可以运行BFS以查找单个路径(findPath
)或查找多个路径(findAllPaths
)。见评论:
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;
}
}
为了测试它,请考虑以下图表:
运行测试:
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);
}
输出:
答案 1 :(得分:0)
显然,通过广度优先搜索检索从给定源到给定终端的所有路径是不可能的。考虑以下类图。
对于任何非负整数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
非正式地,图形由两行顶点组成,每行有n
列,左边有一个源节点,右边有一个终端节点。对于从s
到t
的每个路径,您可以选择每列保留在当前行中或切换到另一行。
从2^n
到s
总共有t
个不同的路径,因为每列有两种选择行的可能性。
另一方面,Breadth-First search产生一个运行时界限,它是图的编码长度中的多项式;这意味着广度优先搜索通常不能生成从给定源到给定终端的所有可能路径。此外,如果图形包含一个循环,则通过重复循环,路径的数量可能是无限的。