利用廣度優先遍曆(BFS)計算最短路徑 - Java實現

來源:互聯網
上載者:User

標籤:演算法

我們用字串代表圖的頂點(vertax),來類比學校中Classroom, Square, Toilet, Canteen, South Gate, North Gate幾個地點,然後計算任意兩點之間的最短路徑。

如,我想從North Gate去Canteen, 程式的輸出結果應為:

    BFS: From [North Gate] to [Canteen]:    North Gate    Square    Canteen

首先定義一個演算法介面Algorithm:

public interface Algorithm {    /**     * 執行演算法     */    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;    }    /**     * 執行演算法     */    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;    }}

這裡我們使用原則設計模式,將演算法與Graph類分離,通過在構造Graph對象時傳入一個Algorithm介面的實現來為Graph選擇遍曆演算法。

public Graph(Algorithm algorithm) {        this.algorithm = algorithm;    }

無向圖的儲存結構為鄰接表,這裡用一個Map表示鄰接表,map的key是學校地點(String),value是一個與該地點相連通的地點表(List<String>)。

// 鄰接表    private Map<String, List<String>> adj = new HashMap<>();

然後,編寫Algorithm介面的BFS實現:

/** * 封裝BFS演算法 */public class BroadFristSearchAlgorithm implements Algorithm {    // 儲存已經訪問過的地點    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);                }            }        }    }}

其中,pathMap類型,意為從 value 到 key 的一條路徑。
BFS演算法描述:
1. 將起點標記為已訪問並放入隊列。
2. 從隊列中取出一個頂點,得到與該頂點相通的所有頂點。
3. 遍曆這些頂點,先判斷頂點是否已被訪問過,如果否,標記該點為已訪問,記錄當前路徑,並將當前頂點入列。
4. 重複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());        }    }

利用廣度優先遍曆(BFS)計算最短路徑 - Java實現

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.