1.需求及实现目标
需求
图数据,有向图,给定起点和终点,返回所有可能到达的路径
实现目标
输入:图数据邻接表,起点,终点
输出:起点 到 终点所有可能的路径
举例 关系图如上 输入 start = A ,end = E
输出
我这边业务中最后需要将数据中所有的顶点单独取出,拼成前端G6需要的json,这里就只简单写个demo;
还有一些情况
上图有B 点这种环的情况 start = A ,end=H 的话, 需要将这个环也输出出来,即所有可能到达的路径.
2.代码实现
思路
使用图的遍历,从起点开始,查找终点.
只用广度遍历没实现明白.只能找一种路径.
只用深度遍历,想找所有可能的路径就需要深度的时候往回退,关系多了的时候巨慢.
两者结合
在广度遍历的时候,进行深度遍历,深度遍历只要能查到一种到达终点的方式便记录该顶点.
public class TestGraph {
public static void main(String[] args) {
Graph graph = new Graph();
addData(graph);
Map<String, List<Edge>> adjacencyList = graph.getAdjacencyList();
String start = "A";
String end = "E";
List<Edge> re = findAllPathBFS(adjacencyList, start, end);
for (Edge edge : re) {
System.out.println(edge.getSource() + "-->" + edge.getDestination());
}
}
//核心查找方法
private static List<Edge> findAllPathBFS(Map<String, List<Edge>> adjacencyList, String start, String end) {
List<Edge> re = new ArrayList<>();
Queue<String> queue = new LinkedList<>();
List<String> vz = new ArrayList<>();
queue.offer(start);
vz.add(start);
while (!queue.isEmpty()) {
String poll = queue.poll();
List<Edge> edges = adjacencyList.get(poll);
//防止到达终点继续广度遍历
if (!poll.equals(end)){
for (Edge edge : edges) {
if (!vz.contains(edge.getDestination())) {
queue.offer(edge.getDestination());
vz.add(edge.getDestination());
}
if (findPathDFS(adjacencyList, edge.getDestination(), end)) {
re.add(new Edge(poll, edge.getDestination()));
}
}
}
}
return re;
}
private static boolean findPathDFS(Map<String, List<Edge>> adjacencyList, String start, String end) {
return dfsStack(adjacencyList, start, end);
}
private static boolean dfsStack(Map<String, List<Edge>> adjacencyList, String start, String end) {
Stack<String> data = new Stack<>();
List<String> visited = new ArrayList<>();
data.push(start);
while (!data.isEmpty()) {
String pop = data.pop();
if (pop.equals(end)){
return true;
}
if (!visited.contains(pop)) {
visited.add(pop);
for (Edge neighbor : adjacencyList.get(pop)) {
if (!visited.contains(neighbor.getDestination())) {
data.push(neighbor.getDestination());
}
}
}
}
return false;
}
// 深度优先搜索递归函数
private static boolean dfsD(Map<String, List<Edge>> adjacencyList, String start, String end, List<String> visited, boolean b) {
visited.add(start);
if (start.equals(end)) {
b = true;
} else {
for (Edge neighbor : adjacencyList.get(start)) {
if (!visited.contains(neighbor.getDestination())) {
dfsD(adjacencyList, neighbor.getDestination(), end, visited, b);
}
}
}
visited.remove(start); // 重置当前顶点的访问状态
return b;
}
private static void addData(Graph graph) {
graph.addVertex("A");
graph.addVertex("B");
graph.addVertex("C");
graph.addVertex("D");
graph.addVertex("E");
graph.addVertex("F");
graph.addVertex("G");
graph.addEdge("A", "B");
graph.addEdge("A", "C");
graph.addEdge("B", "D");
graph.addEdge("C", "D");
graph.addEdge("C", "E");
graph.addEdge("D", "E");
graph.addEdge("D", "F");
graph.addEdge("F", "A"); // 添加一个环
graph.addEdge("F", "G");
}
static class Graph {
private int V; // 顶点数
private Map<String, List<Edge>> adjacencyList; // 邻接表
public Graph() {
V = 0;
adjacencyList = new HashMap<>();
}
// 添加顶点
public void addVertex(String vertex) {
adjacencyList.put(vertex, new ArrayList<>());
V++;
}
// 添加边
public void addEdge(String source, String destination) {
Edge edge = new Edge(source, destination);
adjacencyList.get(source).add(edge);
}
public int getV() {
return V;
}
public Map<String, List<Edge>> getAdjacencyList() {
return adjacencyList;
}
}
static class Edge {
private String source;
private String destination;
public Edge(String source, String destination) {
this.source = source;
this.destination = destination;
}
public String getSource() {
return source;
}
public String getDestination() {
return destination;
}
}
}
代码融合到业务中目前看实现的没啥问题,发出来也是看看有没有大佬帮忙指点一下,看看有没有错误,或者更好的方式.