PHP實(shí)現(xiàn)的迪科斯徹(Dijkstra)最短路徑算法實(shí)例
本文實(shí)例講述了PHP實(shí)現(xiàn)的迪科斯徹(Dijkstra)最短路徑算法。分享給大家供大家參考,具體如下:
一、待解決問題
單源最短路徑問題,在給定有向圖中求一個(gè)頂點(diǎn)(單源頂點(diǎn))到其他所有頂點(diǎn)的最短路徑問題。在下圖中,每條邊上有一個(gè)權(quán)值,希望求解A到所有其他頂點(diǎn)(B/C/D/E/F/G)的最短路徑。
二、問題分析(最短路徑的子結(jié)構(gòu)同樣最優(yōu)性)
如果P(A,G)是從頂點(diǎn)A到G的最短路徑,假設(shè)D和F是這條路徑上的中間點(diǎn),那么P(D,F)一定時(shí)從D到F的最短路徑。如果P(D,F)不是D到F的最短路徑,那必然存在某一個(gè)節(jié)點(diǎn)M的另一條D到F的路徑可以使P(A,B...M...F,G)比P(A,G)小,自相矛盾。
有了這樣的性質(zhì),我們可以了解Dijkstra算法。
三、Dijkstra算法
Dijkstra 算法,又叫迪科斯徹算法(Dijkstra),又稱為單源最短路徑算法,所謂單源是在一個(gè)有向圖中,從一個(gè)頂點(diǎn)出發(fā),求該頂點(diǎn)至所有可到達(dá)頂點(diǎn)的最短路徑問題。 問題描述為設(shè)G=(V,E)是一個(gè)有向圖,V表示頂點(diǎn),E表示邊。它的每一條邊(i,j)屬于E,都有一個(gè)非負(fù)權(quán)W(I,j),在G中指定一個(gè)結(jié)點(diǎn)v0,要求把從v0到G的每一個(gè)接vj(vj屬于V)的最短有向路徑找出來(或者指出不存在)。 Dijstra算法是運(yùn)用貪心的策略,從源點(diǎn)開始,不斷地通過相聯(lián)通的點(diǎn)找出到其他點(diǎn)的最短距離。
Dijkstra的貪心應(yīng)用在他利用(二)中的性質(zhì),不斷地選取“最近”的節(jié)點(diǎn)并試探每個(gè)節(jié)點(diǎn)的所有可能存在鏈接,以起始點(diǎn)為中心向外層層擴(kuò)展,直到擴(kuò)展到終點(diǎn)為止。對于源點(diǎn)A,逐步擴(kuò)展,根據(jù)dist[j]=min{dist[j],dist[i]+matrix[i][j]}更新與i直接相鄰的頂點(diǎn)信息。
算法描述
1)算法思想:
設(shè)G=(V,E)是一個(gè)帶權(quán)有向圖,把圖中頂點(diǎn)集合V分成兩組,第一組為已求出最短路徑的頂點(diǎn)集合(用S表示,初始時(shí)S中只有一個(gè)源點(diǎn),以后每求得一條最短路徑 , 就將加入到集合S中,直到全部頂點(diǎn)都加入到S中,算法就結(jié)束了),第二組為其余未確定最短路徑的頂點(diǎn)集合(用U表示),按最短路徑長度的遞增次序依次把第二組的頂點(diǎn)加入S中。在加入的過程中,總保持從源點(diǎn)v到S中各頂點(diǎn)的最短路徑長度不大于從源點(diǎn)v到U中任何頂點(diǎn)的最短路徑長度。此外,每個(gè)頂點(diǎn)對應(yīng)一個(gè)距離,S中的頂點(diǎn)的距離就是從v到此頂點(diǎn)的最短路徑長度,U中的頂點(diǎn)的距離,是從v到此頂點(diǎn)只包括S中的頂點(diǎn)為中間頂點(diǎn)的當(dāng)前最短路徑長度。
2)算法步驟:
a.初始時(shí),S只包含源點(diǎn),即S={v},v的距離為0。U包含除v外的其他頂點(diǎn),即:U={其余頂點(diǎn)},若v與U中頂點(diǎn)u有邊,則<u,v>正常有權(quán)值,若u不是v的出邊鄰接點(diǎn),則<u,v>權(quán)值為∞。
b.從U中選取一個(gè)距離v最小的頂點(diǎn)k,把k,加入S中(該選定的距離就是v到k的最短路徑長度)。
c.以k為新考慮的中間點(diǎn),修改U中與k相鄰的各頂點(diǎn)的距離;若從源點(diǎn)v到頂點(diǎn)u的距離(經(jīng)過頂點(diǎn)k)比原來距離(不經(jīng)過頂點(diǎn)k)短,則修改頂點(diǎn)u的距離值,修改后的距離值為頂點(diǎn)k的距離加上k與u邊上的權(quán)。
d.重復(fù)步驟b和c直到所有頂點(diǎn)都包含在S中。
四、算法PHP實(shí)現(xiàn)
<?php class Dijkstra { private $G; public function __construct() { //有向圖存儲 $this->G = array( array(0,1,2,0,0,0,0), array(0,0,0,1,2,0,0), array(0,0,0,0,0,2,0), array(0,0,0,0,0,1,3), array(0,0,0,0,0,0,3), array(0,0,0,0,0,0,1), array(0,0,0,0,0,0,0), ); } public function calculate() { // 存儲已經(jīng)選擇節(jié)點(diǎn)和剩余節(jié)點(diǎn) $U = array(0); $V = array(1,2,3,4,5,6); // 存儲路徑上節(jié)點(diǎn)距離源點(diǎn)的最小距離 $d = array(); //初始化圖中節(jié)點(diǎn)與源點(diǎn)0的最小距離 for($i=1;$i<7;$i++) { if($this->G[0][$i]>0) { $d[$i] = $this->G[0][$i]; } else { $d[$i] = 1000000; } } // n-1次循環(huán)完成轉(zhuǎn)移節(jié)點(diǎn)任務(wù) for($l=0;$l<6;$l++) { // 查找剩余節(jié)點(diǎn)中距離源點(diǎn)最近的節(jié)點(diǎn)v $current_min = 100000; $current_min_v = 0; foreach($V as $k=>$v) { if($d[$v] < $current_min) { $current_min = $d[$v]; $current_min_v = $v; } } //從V中更新頂點(diǎn)到U中 array_push($U,$current_min_v); array_splice($V,array_search($current_min_v,$V),1); //更新 foreach($V as $k=>$u) { if($this->G[$current_min_v][$u]!=0&&$d[$u]>$d[$current_min_v]+$this->G[$current_min_v][$u]) { $d[$u] = $d[$current_min_v]+$this->G[$current_min_v][$u]; } } } foreach($d as $k => $u) { echo $k.'=>'.$u.'<br>'; } } } ?>
調(diào)用類:
$D = new Dijkstra; $D->calculate();
執(zhí)行結(jié)果:
1=>1 2=>2 3=>2 4=>3 5=>3 6=>4
更多關(guān)于PHP相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《PHP數(shù)據(jù)結(jié)構(gòu)與算法教程》、《PHP基本語法入門教程》、《php面向?qū)ο蟪绦蛟O(shè)計(jì)入門教程》、《php字符串(string)用法總結(jié)》及《php查找技巧與方法總結(jié)》
希望本文所述對大家PHP程序設(shè)計(jì)有所幫助。
- PHP機(jī)器學(xué)習(xí)庫php-ml的簡單測試和使用方法
- PHP實(shí)現(xiàn)圖的鄰接矩陣表示及幾種簡單遍歷算法分析
- PHP對稱加密算法(DES/AES)類的實(shí)現(xiàn)代碼
- PHP基于回溯算法解決n皇后問題的方法示例
- php實(shí)現(xiàn)的生成迷宮與迷宮尋址算法完整實(shí)例
- PHP實(shí)現(xiàn)的貪婪算法實(shí)例
- 利用PHP實(shí)現(xiàn)開心消消樂的算法示例
- PHP使用棧解決約瑟夫環(huán)問題算法示例
- PHP基于遞歸實(shí)現(xiàn)的約瑟夫環(huán)算法示例
- PHP實(shí)現(xiàn)機(jī)器學(xué)習(xí)之樸素貝葉斯算法詳解
相關(guān)文章
php多線程實(shí)現(xiàn)方法及用法實(shí)例詳解
這篇文章主要介紹了php多線程實(shí)現(xiàn)方法及用法實(shí)例,PHP多線程實(shí)現(xiàn)方法和fsockopen函數(shù)有關(guān),需要的朋友可以參考下2015-10-10PHP簡單獲取網(wǎng)站百度搜索和搜狗搜索收錄量的方法
這篇文章主要介紹了PHP簡單獲取網(wǎng)站百度搜索和搜狗搜索收錄量的方法,涉及php網(wǎng)頁文件的讀取及正則替換的相關(guān)操作技巧,需要的朋友可以參考下2016-08-08