S9-算法-弗洛伊德算法【2020-02-11】

總目錄:地址如下看總綱

http://www.reibang.com/p/929ca9e209e8

1持偏、應(yīng)用場景-最短路徑問題

建國時期逛钻,史萊村鄉(xiāng)有7個村莊(A, B, C, D, E, F, G) 肺樟,現(xiàn)在有六個郵差忧吟,從G點出發(fā)依疼,需要分別把郵件分別送到 A, B, C , D, E, F 六個村莊高蜂,各個村莊的距離用邊線表示(權(quán)) 椎眯,比如 A – B 距離 5公里
問:
1、如何計算出G村莊到 其它各個村莊的最短距離?
2再姑、如果從其它點出發(fā)到各個點的最短距離又是多少?


image.png

2萌抵、弗洛伊德(Floyd)算法介紹

(1)和Dijkstra算法一樣,弗洛伊德(Floyd)算法也是一種用于尋找給定的加權(quán)圖中頂點間最短路徑的算法。
(2)該算法名稱以創(chuàng)始人之一绍填、1978年圖靈獎獲得者萎坷、斯坦福大學(xué)計算機科學(xué)系教授羅伯特·弗洛伊德命名
弗洛伊德算法(Floyd)計算圖中各個頂點之間的最短路徑
(3)迪杰斯特拉算法用于計算圖中某一個頂點到其他頂點的最短路徑。
(4)弗洛伊德算法 VS 迪杰斯特拉算法:迪杰斯特拉算法通過選定的被訪問頂點沐兰,求出從出發(fā)訪問頂點到其他頂點的最短路徑哆档;弗洛伊德算法中每一個頂點都是出發(fā)訪問點,所以需要將每一個頂點看做被訪問頂點住闯,求出從每一個頂點到其他頂點的最短路徑瓜浸。

3、弗洛伊德算法思路

1比原、說明:不必插佛,深究
(1)設(shè)置頂點vi到頂點vk的最短路徑已知為Lik,頂點vk到vj的最短路徑已知為Lkj量窘,頂點vi到vj的路徑為Lij雇寇,則vi到vj的最短路徑為:min((Lik+Lkj),Lij),vk的取值為圖中所有頂點蚌铜,則可獲得vi到vj的最短路徑
(2)至于vi到vk的最短路徑Lik或者vk到vj的最短路徑Lkj锨侯,是以同樣的方式獲得

2、圖解:主要學(xué)習(xí)方式

核心是兩個二維數(shù)據(jù):一是初始的各頂點的距離表冬殃,二是初始前驅(qū)頂點關(guān)系表囚痴,還有三層循環(huán)


image.png

image.png

步驟圖:
(1)廣度大圖


image.png

(2)
image.png

(3)根據(jù)三種情況,演變出箭頭指向圖审葬,為三種情況的變化
(4)
image.png

(5)說明:
情況一:將C-G從N替換為9深滚,因為這樣更短
情況二:將C-B從N替換為12,因為距離更短
情況三:將G-B不替換,因為原本不經(jīng)過A的時候距離才3涣觉,經(jīng)過之后距離為7痴荐,更遠了,所以不替換

4官册、代碼

public class FloydAlgorithm {
    public static void main(String[] args) {

        // 測試圖是否創(chuàng)建成功
        char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
        // 創(chuàng)建鄰接矩陣
        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};

        // 創(chuàng)建 Graph 對象
        Graph graph = new Graph (vertex.length, matrix, vertex);
        // 調(diào)用弗洛伊德算法
        graph.floyd ();
        graph.show ();
    }


}

// 構(gòu)建圖
class Graph {
    private char[] vertex;   // 存放頂點的數(shù)組
    private int[][] dis;     // 保存各個頂點出發(fā)到其他頂點的距離(同樣也是保留最終結(jié)果)
    private int[][] pre;     // 保存到達目標頂點的前驅(qū)頂點

    /**
     * 構(gòu)造器
     *
     * @param length 定義大小
     * @param matrix 鄰接矩陣
     * @param vertex 頂點數(shù)組
     */
    public Graph(int length, int[][] matrix, char[] vertex) {
        this.vertex = vertex;
        this.dis = matrix;
        this.pre = new int[length][length];
        // 初始化 pre 數(shù)據(jù)生兆,注:存放應(yīng)是前驅(qū)頂點的下標
        for (int i = 0; i < length; i++) {
            Arrays.fill (pre[i], i);
        }
    }

    // 顯示 pre 和 dis 兩個二位數(shù)組
    public void show() {
        // 為了便于閱讀,進而優(yōu)化輸出
        char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
        for (int k = 0; k < dis.length; k++) {
            // 先輸出前驅(qū)數(shù)組 pre 的一行
            for (int i = 0; i < dis.length; i++) {
                System.out.print (pre[k][i] + " ");
            }
            // 再輸出dis 數(shù)組的一行
            for (int i = 0; i < dis.length; i++) {
                System.out.print ("(" + vertex[k] + "到" + vertex[i] + "的最短路徑是" + dis[k][i] + ") ");
            }
            System.out.println ( );
            System.out.println ( );
        }
    }

    // 核心:弗洛伊德算法, 比較容易理解攀隔,而且容易實現(xiàn)(三層循環(huán))
    public void floyd() {
        // 變量保持距離
        int len = 0;
        // 對中間頂點遍歷皂贩, k 就是中間頂點的下標 [A, B, C, D, E, F, G]
        for (int k = 0; k < dis.length; k++) {
            // 從i頂點開始出發(fā) [A, B, C, D, E, F, G]
            for (int i = 0; i < dis.length; i++) {
                // 到達j頂點 // [A, B, C, D, E, F, G]
                for (int j = 0; j < dis.length; j++) {
                    // 求出從i 頂點出發(fā)栖榨,經(jīng)過 k中間頂點昆汹,到達 j 頂點距離
                    len = dis[i][k] + dis[k][j];
                    if (len < dis[i][j]) {       // 若len小于 dis[i][j]
                        dis[i][j] = len;        // 更新距離
                        pre[i][j] = pre[k][j];  // 更新前驅(qū)頂點
                    }
                }
            }
        }
    }
}

5、倉庫坐標

image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末婴栽,一起剝皮案震驚了整個濱河市满粗,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌愚争,老刑警劉巖映皆,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件挤聘,死亡現(xiàn)場離奇詭異,居然都是意外死亡捅彻,警方通過查閱死者的電腦和手機组去,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來步淹,“玉大人从隆,你說我怎么就攤上這事$择桑” “怎么了键闺?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長澈驼。 經(jīng)常有香客問我辛燥,道長,這世上最難降的妖魔是什么缝其? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任挎塌,我火速辦了婚禮,結(jié)果婚禮上内边,老公的妹妹穿的比我還像新娘勃蜘。我一直安慰自己,他們只是感情好假残,可當我...
    茶點故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布缭贡。 她就那樣靜靜地躺著,像睡著了一般辉懒。 火紅的嫁衣襯著肌膚如雪阳惹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天眶俩,我揣著相機與錄音莹汤,去河邊找鬼。 笑死颠印,一個胖子當著我的面吹牛纲岭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播线罕,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼止潮,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了钞楼?” 一聲冷哼從身側(cè)響起喇闸,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤愉粤,失蹤者是張志新(化名)和其女友劉穎远舅,沒想到半個月后桑阶,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體霜运,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年刻蟹,在試婚紗的時候發(fā)現(xiàn)自己被綠了逗旁。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡舆瘪,死狀恐怖痢艺,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情介陶,我是刑警寧澤堤舒,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站哺呜,受9級特大地震影響舌缤,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜某残,卻給世界環(huán)境...
    茶點故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一国撵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧玻墅,春花似錦介牙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至剩拢,卻和暖如春线得,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背徐伐。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工贯钩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人办素。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓角雷,卻偏偏與公主長得像,于是被迫代替她去往敵國和親性穿。 傳聞我的和親對象是個殘疾皇子勺三,可洞房花燭夜當晚...
    茶點故事閱讀 45,066評論 2 355

推薦閱讀更多精彩內(nèi)容