《演算法導論》第24章 單源最短路徑

2021-08-31 11:50:07 字數 4298 閱讀 2911

最短路徑的最優子結構

最短路徑的子路徑也是最短路徑。

負權重的邊

權重為負數的邊。(我的理解:大概知道這個就可以了)

環路

最短路徑既不能包含正的環路,也不能包含負的環路。(正的環路,我覺得正常人想走最短的路,都不會在那裡打圈,除非路就是圓的;負環路你多繞幾圈,最後權重想變多小變多小,就很沒意思。)

最短路徑的表示

每個節點保持乙個前驅屬性v.π,指向它的前乙個結點。(這樣可以串成一串)

鬆弛操作

說白了就是就是檢查一下繞小路會不會更近。

v.d:表示s到v的最短路徑估計

接下來書中還有一堆性質,我就放圖,我自己也沒看,感覺很每意思,就是感覺把一些簡單的東西說的很複雜,顯得十分高大上。

我的思路:

這邊為什麼要先對點迴圈,然後再套乙個對邊的迴圈鬆弛呢?因為第一次鬆弛的時候,部分地方還不是最短路徑。這邊思路真的不是很好描述:最好的辦法就是自己按照它的流程走一遍!

1、對有向無環圖進行拓撲排序

2、再進行bellman類似操作

這一章我模稜兩可地看了看,emmm不知道它到底要講些什麼,如果你知道的話,請告訴我,謝謝!那麼我就要跳過這部分了。

dijkstra演算法解決的是帶權重的有向圖上單源最短路徑問題,要求所有邊權重大於0 。

我的感覺:它就是乙個改進的prim演算法。

我的思路:

1、每個點都有乙個mark屬性標誌著是否已經在路徑中

2、將邊從小排到大

3、如果點沒有全部加入到路徑中,從小到大遍歷每條邊,如果邊的起點在路徑中,邊的終點沒在路徑中,就把終點的前驅設定為起點,同時終點的mark屬性變為true

4、開始重新遍歷邊

24.5最短路徑性質的證明

四五兩章都非常的理論,我就不看了,真的很討厭這種看的頭疼又看不懂的東西。

以下就是**部分了(建議貼上到自己的編輯器中執行)

bellman.h

#pragma once

#define bellv 5/*點的數量*/

#define belle 10/*邊的數量*/

/*點*/

typedef struct bellv

bellv;

/*邊*/

typedef struct

belle;

/*圖*/

typedef struct

bellg;

/*初始化*/

void initbell(bellg* &g, bellv* root);

/*鬆弛操作*/

void bellrelax(bellv* u, bellv* v, int w);

/*bellman演算法*/

bool bellman(bellg* &g, bellv* root);

/*列印路徑*/

void bellprint(bellv *root, bellv *end);

/*測試函式*/

void testbellman();

bellman.cpp

#include "bellman.h"

#include#include#includeusing namespace std;

/*初始化*/

void initbell(bellg* &g,bellv* root)

root->d = 0;/*源結點*/

}/*鬆弛操作*/

void bellrelax(bellv* u, bellv* v, int w)

}/*bellman演算法*/

bool bellman(bellg* &g,bellv* root)

} for (i = 0; i < belle; i++)/*檢測是否有負迴路*/

if (g->e[i]->end->d > g->e[i]->start->d + g->e[i]->w)

return false;

return true;

}/*列印路徑*/

void bellprint(bellv *root, bellv *end)

}/*測試函式*/

void testbellman()

} }else

cout << "error!";

}

主函式

#include "bellman.h"

#include int main()

執行結果dijstra.h

#pragma once

#define dijv 5/*點的數量*/

#define dije 10/*邊的數量*/

/*點*/

typedef struct dijv

dijv;

/*邊*/

typedef struct

dije;

/*圖*/

typedef struct

dijg;

/*比較函式*/

bool dijcmp(dije* x, dije* y);

/*dijkstra演算法*/

void dijkstra(dijg* &g, dijv* root);

/*列印路徑*/

void dijprint(dijv *root, dijv *end);

/*測試函式*/

void testdijkstra();

dijstra.cpp

#include "dijstra.h"

#include#include#include/*sort排序函式所需標頭檔案*/

#includeusing namespace std;

/*比較函式*/

bool dijcmp(dije* x, dije* y)

/*dijkstra演算法*/

void dijkstra(dijg* &g,dijv* root)

root->mark = true;

sort(g->e, g->e + dije, dijcmp);/*按權重排序*/

j = 0;

while (j < dijv - 1)/*還有點沒有被選中*/

} }}

/*列印路徑*/

void dijprint(dijv *root, dijv *end)

}/*測試函式*/

void testdijkstra()

}}

主函式

#include "dijstra.h"

#include int main()

執行結果

《演算法導論》第24章 單源最短路徑

單元最短路徑問題 單源最短路徑問題,試 決從乙個原點到圖中其他所有點的最短路徑問題。此問題的變體有單終點最短路徑問題,單終點最短路徑問題和每對頂點間最短路徑問題。可以相應理解為一對多 多對 一 一對一和多對多的對映關係。負權值邊和負權迴路 某些權值可以是負的,這些邊稱為是負權值邊。負權迴路指的是構成...

演算法導論筆記 單源最短路徑

本文所貼示的偽 均 演算法導論 本文只是對其中 單源最短路徑 章節的簡單總結,許多數學證明過程已忽略。最短路徑的定義 給定乙個圖g v,e 希望找到從給定源節點s v 到每個結點v v 的最短路徑。單源最短路徑可以用來解決許多其他問題,包括 1 單目的地最短路徑問題 找到從每個結點v到給定目的結點t...

單源最短路徑演算法

簡單介紹 最短路徑演算法是圖演算法中的經典演算法,是用於解決圖中某個頂點到另外乙個頂點所經過路徑的花銷最小 這裡的花銷可能是時間也可能指費用等 dijkstra是用於解決單源最短路徑的經典演算法。圖的儲存方式 鄰接矩陣 在鄰接矩陣中,要獲取某個結點的出度和入讀,是通過掃瞄結點所在臨界矩陣中的行列完成...