Java實現(xiàn)利用廣度優(yōu)先遍歷(BFS)計算最短路徑的方法
本文實例講述了Java實現(xiàn)利用廣度優(yōu)先遍歷(BFS)計算最短路徑的方法。分享給大家供大家參考。具體分析如下:
我們用字符串代表圖的頂點(vertax),來模擬學(xué)校中Classroom, Square, Toilet, Canteen, South Gate, North Gate幾個地點,然后計算任意兩點之間的最短路徑。
如下圖所示:

如,我想從North Gate去Canteen, 程序的輸出結(jié)果應(yīng)為:
BFS: From [North Gate] to [Canteen]: North Gate Square Canteen
首先定義一個算法接口Algorithm:
public interface Algorithm {
/**
* 執(zhí)行算法
*/
void perform(Graph g, String sourceVertex);
/**
* 得到路徑
*/
Map<String, String> getPath();
}
然后,定義圖:
/**
* (無向)圖
*/
public class Graph {
// 圖的起點
private String firstVertax;
// 鄰接表
private Map<String, List<String>> adj = new HashMap<>();
// 遍歷算法
private Algorithm algorithm;
public Graph(Algorithm algorithm) {
this.algorithm = algorithm;
}
/**
* 執(zhí)行算法
*/
public void done() {
algorithm.perform(this, firstVertax);
}
/**
* 得到從起點到{@code vertex}點的最短路徑
* @param vertex
* @return
*/
public Stack<String> findPathTo(String vertex) {
Stack<String> stack = new Stack<>();
stack.add(vertex);
Map<String, String> path = algorithm.getPath();
for (String location = path.get(vertex) ; false == location.equals(firstVertax) ; location = path.get(location)) {
stack.push(location);
}
stack.push(firstVertax);
return stack;
}
/**
* 添加一條邊
*/
public void addEdge(String fromVertex, String toVertex) {
if (firstVertax == null) {
firstVertax = fromVertex;
}
adj.get(fromVertex).add(toVertex);
adj.get(toVertex).add(fromVertex);
}
/**
* 添加一個頂點
*/
public void addVertex(String vertex) {
adj.put(vertex, new ArrayList<>());
}
public Map<String, List<String>> getAdj() {
return adj;
}
}
這里我們使用策略設(shè)計模式,將算法與Graph類分離,通過在構(gòu)造Graph對象時傳入一個Algorithm接口的實現(xiàn)來為Graph選擇遍歷算法。
public Graph(Algorithm algorithm) {
this.algorithm = algorithm;
}
無向圖的存儲結(jié)構(gòu)為鄰接表,這里用一個Map表示鄰接表,map的key是學(xué)校地點(String),value是一個與該地點相連通的地點表(List<String>)。
// 鄰接表 private Map<String, List<String>> adj = new HashMap<>();
然后,編寫Algorithm接口的BFS實現(xiàn):
/**
* 封裝BFS算法
*/
public class BroadFristSearchAlgorithm implements Algorithm {
// 保存已經(jīng)訪問過的地點
private List<String> visitedVertex;
// 保存最短路徑
private Map<String, String> path;
@Override
public void perform(Graph g, String sourceVertex) {
if (null == visitedVertex) {
visitedVertex = new ArrayList<>();
}
if (null == path) {
path = new HashMap<>();
}
BFS(g, sourceVertex);
}
@Override
public Map<String, String> getPath() {
return path;
}
private void BFS(Graph g, String sourceVertex) {
Queue<String> queue = new LinkedList<>();
// 標記起點
visitedVertex.add(sourceVertex);
// 起點入列
queue.add(sourceVertex);
while (false == queue.isEmpty()) {
String ver = queue.poll();
List<String> toBeVisitedVertex = g.getAdj().get(ver);
for (String v : toBeVisitedVertex) {
if (false == visitedVertex.contains(v)) {
visitedVertex.add(v);
path.put(v, ver);
queue.add(v);
}
}
}
}
}
其中,path是Map類型,意為從 value 到 key 的一條路徑。
BFS算法描述:
1. 將起點標記為已訪問并放入隊列。
2. 從隊列中取出一個頂點,得到與該頂點相通的所有頂點。
3. 遍歷這些頂點,先判斷頂點是否已被訪問過,如果否,標記該點為已訪問,記錄當(dāng)前路徑,并將當(dāng)前頂點入列。
4. 重復(fù)2、3,直到隊列為空。
測試用例:
String[] vertex = {"North Gate", "South Gate", "Classroom", "Square", "Toilet", "Canteen"};
Edge[] edges = {
new Edge("North Gate", "Classroom"),
new Edge("North Gate", "Square"),
new Edge("Classroom", "Toilet"),
new Edge("Square", "Toilet"),
new Edge("Square", "Canteen"),
new Edge("Toilet", "South Gate"),
new Edge("Toilet", "South Gate"),
};
@Test
public void testBFS() {
Graph g = new Graph(new BroadFristSearchAlgorithm());
addVertex(g);
addEdge(g);
g.done();
Stack<String> result = g.findPathTo("Canteen");
System.out.println("BFS: From [North Gate] to [Canteen]:");
while (!result.isEmpty()) {
System.out.println(result.pop());
}
}
希望本文所述對大家的java程序設(shè)計有所幫助。
相關(guān)文章
Spring MVC文件上傳大小和類型限制以及超大文件上傳bug問題
這篇文章主要介紹了Spring MVC文件上傳大小和類型限制以及超大文件上傳bug問題,非常具有實用價值,需要的朋友可以參考下2017-10-10
Java并發(fā)編程中的ReentrantLock類詳解
這篇文章主要介紹了Java并發(fā)編程中的ReentrantLock類詳解,ReentrantLock是juc.locks包中的一個獨占式可重入鎖,相比synchronized,它可以創(chuàng)建多個條件等待隊列,還支持公平/非公平鎖、可中斷、超時、輪詢等特性,需要的朋友可以參考下2023-12-12
Spring?AI?+?混元帶你實現(xiàn)企業(yè)級穩(wěn)定可部署的AI業(yè)務(wù)智能體
我們深入探討了Spring?AI在智能體構(gòu)建中的實際應(yīng)用,特別是在企業(yè)環(huán)境中的價值與效能,通過逐步實現(xiàn)一個本地部署的智能體解決方案,我們不僅展示了Spring?AI的靈活性與易用性,還強調(diào)了它在推動AI技術(shù)與業(yè)務(wù)深度融合方面的潛力,感興趣的朋友一起看看吧2024-11-11

