算法其實很簡單—迪傑斯特拉(Dijkstra)算法

目錄

1.迪傑斯特拉(Dijkstra)算法介紹

2.克魯斯卡爾最佳實踐公交站問題

3.迪傑斯特拉(Dijkstra)算法過程

4.代碼實現


1.迪傑斯特拉(Dijkstra)算法介紹

迪傑斯特拉(Dijkstra)算法是典型最短路徑算法,用於計算-一個節點到其他節點的最

短路徑。它的主要特點是以起始點爲中心向外層層擴展(廣^度優先搜索思想),直到

擴展到終點爲止。

2.克魯斯卡爾最佳實踐公交站問題

 

1)戰爭時期,勝利鄉有7個村莊(A,B,C,D,E,F,G),現在有六個郵差,從G點出發,需要分別把郵件分別送到A,B,C,D,E,F六個村莊

2)各個村莊的距離用邊線表示(權),比如A-B距離5公里

3) 問:如何計算出G村莊到其它各個村莊的最短距離?

4)如果從其它點出 發到各個點的最短距離又是多少?

3.迪傑斯特拉(Dijkstra)算法過程

設置出發頂點爲v,頂點集金V{v1,2v.,..},v到V中各頂點的距離構成距離集合Dis,Dis{d1,2,d...},. Dis集 合記錄着v到圖中各頂點的距離(到自身可以看作0,v到vi距離對應爲di)

1)從Dis中選擇值最小的di並移出Dis集合,同時移出V集合中對應的頂點vi,此時的v到vi即爲最短路徑

2)更新Dis集合, 更新規則爲:比較v到V集合中項點的距離值, 與v通過vi到V集合中頂點的距離值,保留值較小的一個(同時也應該更新頂點的前驅節點爲vi,表明是通過vi到達的)

3) 重複執行兩步驟,直到最短路徑項點爲目標頂點即可結束

4.代碼實現

package com.example.datastructureandalgorithm.dijkstra;

import java.util.Arrays;

/**
 * 迪傑斯特拉算法
 *
 * @author 浪子傑
 * @version 1.0
 * @date 2020/6/27
 */
public class DijkstraDemo {

    public static void main(String[] args) {
        char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
        int[][] matrix = new int[vertex.length][vertex.length];
        final int N = 65535;
        matrix[0] = new int[]{0, 5, 7, N, N, N, 2};
        matrix[1] = new int[]{5, 0, N, 9, N, N, 3};
        matrix[2] = new int[]{7, N, 0, N, 8, N, N};
        matrix[3] = new int[]{N, 9, N, 0, N, 4, N};
        matrix[4] = new int[]{N, N, 8, N, 0, 5, 4};
        matrix[5] = new int[]{N, N, N, 4, 5, 0, 6};
        matrix[6] = new int[]{2, 3, N, N, 4, 6, 0};

        Graph graph = new Graph(vertex, matrix);
        graph.show();
        graph.dsj(6);
        graph.showDjs();
    }
}

class Graph {
    /**
     * 存放頂點的數組
     */
    private char[] vertex;

    /**
     * 鄰接矩陣
     */
    private int[][] matrix;

    /**
     * 已訪問頂點集合
     */
    private VisitedVertex visitedVertex;

    public Graph(char[] vertex, int[][] matrix) {
        this.vertex = vertex;
        this.matrix = matrix;
    }

    public void show() {
        for (int[] ints : matrix) {
            System.out.println(Arrays.toString(ints));
        }
    }

    public void dsj(int index) {
        visitedVertex = new VisitedVertex(vertex.length, index);
        update(index);
        for (int i = 1; i < vertex.length; i++) {
            // 找到新的訪問節點
            index = visitedVertex.updateArr();
            // 繼續更新
            update(index);
        }
    }

    /**
     * 更新index節點到周圍節點的距離和前驅節點
     *
     * @param index
     */
    public void update(int index) {
        // 循環鄰接矩陣
        for (int i = 0; i < matrix[index].length; i++) {
            // 到第i個節點的距離爲,出發頂點到index距離+index到i節點的距離
            int length = visitedVertex.getDis(index) + matrix[index][i];
            // 和出發頂點到i頂點距離進行比較
            if (!visitedVertex.in(i) && length < visitedVertex.getDis(i)) {
                visitedVertex.updateDis(i, length);
                visitedVertex.updatePre(i, index);
            }
        }
    }

    public void showDjs() {
        visitedVertex.showDjs();
    }
}

//已訪問頂點集合
class VisitedVertex {
    /**
     * 記錄各個頂點是否訪問過1表示訪問過, 0未訪問,會動態更新
     */
    public int[] already_arr;
    /**
     * 每個下標對應的值爲前- -個頂點下標,會動態更新
     */
    public int[] pre_visited;
    /**
     * 記錄出發頂點到其他所有頂點的距離,比如G爲出發頂點,
     * 就會記錄G到其它項點的距離,會動態更新,求的最短距離就會存放到dis|
     */
    public int[] dis;

    /**
     * 構造器
     *
     * @param length 表示頂點的個數
     * @param index  表示出發頂點的下標
     */
    public VisitedVertex(int length, int index) {
        this.already_arr = new int[length];
        this.pre_visited = new int[length];
        this.dis = new int[length];
        // 初始化dis數組
        Arrays.fill(dis, 65535);
        // 設置index已經被訪問
        already_arr[index] = 1;
        // 設置出發頂點的訪問距離爲0
        this.dis[index] = 0;
    }

    /**
     * 功能:判斷index項點是否被訪問過
     *
     * @param index
     * @return 如果訪問過, 就返回true, 否則訪問false
     */
    public boolean in(int index) {
        return already_arr[index] == 1;
    }

    /**
     * ※
     * 功能:更新出發頂點到index頂點的距離
     *
     * @param index
     * @param len
     */
    public void updateDis(int index, int len) {
        dis[index] = len;
    }

    /**
     * 功能:更新pre頂點的前驅頂點爲index結點
     *
     * @param pre
     * @param index
     */
    public void updatePre(int pre, int index) {
        pre_visited[pre] = index;
    }

    /**
     * 功能:返回出發頂點到index頂點的距離
     *
     * @param index
     */
    public int getDis(int index) {
        return dis[index];
    }

    /**
     * 繼續訪問並返回新的訪問節點
     *
     * @return
     */
    public int updateArr() {
        int min = 65535, index = 0;
        for (int i = 0; i < already_arr.length; i++) {
            if (already_arr[i] == 0 && getDis(i) < min) {
                min = getDis(i);
                index = i;
            }
        }
        // 更新index已經被訪問
        already_arr[index] = 1;
        return index;
    }

    public void showDjs() {
        char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
        int count = 0;
        for (int i : dis) {
            if (i != 65535) {
                System.out.print(vertex[count] + "(" + dis[count] + ")");
            } else {
                System.out.print(vertex[count] + "(N)");
            }
            count ++;
        }
        System.out.println();
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章