1. 程式人生 > >演算法學習筆記(三) 最短路 Dijkstra 和 Floyd 演算法

演算法學習筆記(三) 最短路 Dijkstra 和 Floyd 演算法

圖論中一個經典問題就是求最短路,最為基礎和最為經典的演算法莫過於 Dijkstra 和 Floyd 演算法,一個是貪心演算法,一個是動態規劃,這也是演算法中的兩大經典代表。用一個簡單圖在紙上一步一步演算, 帶回溯的筆記在這篇

對於平時的練習,一個很厲害的 ACMer 說:“刷水題可以加快我們程式設計的速度,做經典則可以讓我們觸類旁通,初期如果遇見很多編不出,不妨就寫虛擬碼,理思路,在紙上進行整體分析和一步步的演算,然後在轉換成程式碼,再反覆迭代”。Linus 不是也說了 "Nobody actually creates perfect code the first time around, except me. But there’s only one of me."  ^_^  對於演算法的學習,絕大多數都是把問題分解變形,然後套用以前或別人的思路。只有把經典的演算法都爛熟於心時,解決問題時才可以做到不知不覺的套用已有的思路和經驗。

能讓我們走的更遠的只有熱情和方法!當認準一件事有價值時,我們要做的就是長期堅持,既然熟練掌握經典演算法這麼有價值,那麼接下來要做的就是反覆訓練直到爛熟於心 ^_^

單源最短路

給定起點 start, 求到任意點的最短路 Dijkstra 演算法,前提不能有負權邊和孤立點:
  • 貪心演算法:每次找最近的點,區域性最優等於全域性最優,數學歸納法可證
  • 維護起點 start 到每個點的距離
  • 時間複雜度 O(n^2)
  • 附加空間複雜度 O(n)
Dijkstra 演算法虛擬碼:
Q = {}                                       // 已求出到 start 點最短路的點集合,初始為空
d[s] = 0, 其餘值為正無窮大
while (|Q| < |V|)                            // 數學符號|A|表示集合A的點數
    取出不在Q中的最小的d[i]
    for (i相鄰的點j,j不屬於Q)
        d[j] = min(d[j], d[i] + c[i][j])     //維護距離
    Q = Q + {i}

全域性最短路

求出圖中任意兩點最短路,利用 Floyd 演算法,對負權邊仍然有效:
  • 動態規劃:每次加入一個點
  • 維護任意兩點間的距離
  • 時間複雜度 O(n^3)
  • 附加空間複雜度 O(n^2)
Floyd 演算法虛擬碼:        # 直接改成 Python 了,沒辦法就是喜歡 Python :)
for k in range(0, n):			
    for i in range(0, n):
        for j in range(0, n):            
            g[i][j] = min(g[i][j], g[i][k]+g[k][j])

小實驗

一個圖如下所示:


原始碼 ( C 實現)

#include <stdio.h>
#define N 65536

/* 計算有 9 個點的圖的單源最短路  */
void Dijkstra(int graph[9][9],  int start, int path[9]){
	int num=9, min, vertex, i, j;
	int flag[num];
	for(i = 0; i < num; ++i){ 	//初始化所有點都未計算,第一次距離直接讀鄰接矩陣
		path[i] = graph[start][i];
		flag[i] = 0;
	}

	for(i = 0; i < num; ++i){
		min = N;
		for(j = 0; j < num; ++j){
			if(flag[j] == 0 && min > path[j]){	//求未計算過的點中距離 start 最近點
				min = path[j];
				vertex = j;
			}
		}
		flag[vertex] = 1; 	//將上面計算的點標記為計算過
		for(j = 0; j < num; ++j){	//維護所有未計算過點的距離
			if(flag[j] == 0 && path[j] > path[vertex] + graph[vertex][j]){
				path[j] = path[vertex] + graph[vertex][j];
			}
		}
	}
}

/* 計算一個 9 個點的圖所有點到所有點間的最短路 */
void Floyd(int graph[9][9]){
	int num = 9, i, j, k;
	for(k = 0; k < num; ++k){			//中轉點
		for(i = 0; i < num; ++i){		//出發點
			for(j = 0; j < num; ++j){	//到達點
				if(graph[i][j] > graph[i][k] + graph[k][j]){
					graph[i][j] = graph[i][k] + graph[k][j];
				}
			}
		}
	}
}

int main() {
	int graph[9][9]={
			{0, 1, 5, N, N, N, N, N, N},
			{1, 0, 3, 7, 5, N, N, N, N},
			{5, 3, 0, N, 1, 7, N, N, N},
			{N, 7, N, 0, 2, N, 3, N, N},
			{N, 5, 1, 2, 0, 3, 6, 9, N},
			{N, N, 7, N, 3, 0, N, 5, N},
			{N, N, N, 3, 6, N, 0, 2, 7},
			{N, N, N, N, 9, 5, 2, 0, 4},
			{N, N, N, N, N, N, 7, 4, 0}
	};
	int start=0, path[9], i, j;
	Dijkstra(graph, start, path);	//計算結果寫入 path 陣列
	printf("點 %d 到所有點的最短距離:\n", start);
	for(i=0; i<9; ++i){
		printf("%d ",path[i]);
	}

	Floyd(graph); 	//計算後的結果也直接寫入graph
	printf("\n所有點到所有點的最短距離\n");
	for(i=0; i<9; ++i){
		for(j=0; j<9; ++j){
			printf("%d ",graph[i][j]);
		}
		printf("\n");
	}

	return 0;
}

/****** 執行結果 ***********
點 0 到所有點的最短距離:
0 1 4 7 5 8 10 12 16
所有點到所有點的最短距離
0 1 4 7 5 8 10 12 16
1 0 3 6 4 7 9 11 15
4 3 0 3 1 4 6 8 12
7 6 3 0 2 5 3 5 9
5 4 1 2 0 3 5 7 11
8 7 4 5 3 0 7 5 9
10 9 6 3 5 7 0 2 6
12 11 8 5 7 5 2 0 4
16 15 12 9 11 9 6 4 0
*****************************/


相關推薦

演算法學習筆記 短路 Dijkstra Floyd 演算法

圖論中一個經典問題就是求最短路,最為基礎和最為經典的演算法莫過於 Dijkstra 和 Floyd 演算法,一個是貪心演算法,一個是動態規劃,這也是演算法中的兩大經典代表。用一個簡單圖在紙上一步一步演算, 帶回溯的筆記在這篇。 對於平時的練習,一個很厲害的 ACMer 說

最優化學習筆記速下降法

tex track enter water pos 最優 content 分享 clas 最優化學習筆記(三)最速下降法

學習筆記:使用K近鄰演算法檢測Rootkit

      Rootkit是一種特殊的惡意軟體,它的功能是在安裝目標上隱藏自身以及指定的檔案,程序和網路連結等資訊。 1.資料蒐集        KDD 99 TCP連線內容特徵包括hot ,num_faild_login

python3.5《機器學習實戰》學習筆記:k近鄰演算法scikit-learn實戰手寫體識別

轉載請註明作者和出處:http://blog.csdn.net/u013829973 系統版本:window 7 (64bit) 我的GitHub:https://github.com/weepon python版本:python 3.5 IDE:Spy

HMM學習筆記:動態規劃與維特比演算法

學習隱馬爾可夫模型(HMM),主要就是學習三個問題:概率計算問題,學習問題和預測問題。在前面講了概率計算問題:前後向演算法推導,Baum-Welch演算法。最後在這裡講最後的一個問題,預測問題。 預測問題:給定HMM引數

支援向量機學習筆記:非線性支援向量機與SMO演算法

非線性問題 在之前學了線性支援向量機,通過訓練集學習到分離超平面 w x +

機器學習筆記——正則化小二乘法

一. 模型的泛化與過擬合 在上一節中,我們的預測函式為: f(x;ω)=ωTx 其中, x=[x1],ω=[ω1ω0] 上述稱為線性模型,我們也可以將x擴充套件為: x=⎡⎣⎢⎢⎢⎢⎢⎢⎢xn⋮x2x1⎤⎦⎥⎥⎥⎥⎥⎥⎥,ω=⎡⎣⎢⎢⎢⎢⎢⎢⎢ωn⋮

深度學習筆記--目標檢測演算法綜述

目前目標檢測領域的深度學習方法主要分為兩類:two stage的目標檢測演算法;one stage的目標檢測演算法。前者是先由演算法生成一系列作為樣本的候選框,再通過卷積神經網路進行樣本分類;後者則不用產生候選框,直接將目標邊框定位的問題轉化為迴歸問題處理。正是由於兩種方法的

JAVA學習筆記

byte repl efi ber 時間 clas 區分大小寫 增強for size @SuppressWarnings("resource")是用來壓制資源泄露警告的。比如使用io類,最後沒有關閉。Set集合特點:1)無序,不隨機2)元素唯一3)沒下標註意:Collect

thinkphp5.0學習筆記獲取信息,變量,綁定參數

名稱 自動識別 參數順序 query images 報錯 oca nds arc 1.構造函數: 控制器類必須繼承了\think\Controller類,才能使用: 方法_initialize 代碼: <?php namespace app\lian\control

python學習筆記

list 內存 寫入 odin move 列表 付出 open ada 文件的操作一般分三步: 1、打開文件,獲取文件的指針(句柄) 2、通過指針(句柄)操作文件 3、關閉文件 現在有以下文件: 我們為愛還在學 學溝通的語言

Redis學習筆記常用命令整理

mes ember nbsp end 插入 學習筆記 頻道 hash value Redis 常用命令 1.DEL key 刪除key2.EXISTS key 檢查key是否存在3.KEYS * 查看所有的key4.EXPIRE key seconds 設置key的過期時

Django 學習筆記模板導入

文件 文件中 訪問 from lang sts class rom 網頁 本章內容是將一個html網頁放進模板中,並運行服務器將其展現出來。 平臺:windows平臺下Liunx子系統 目前的目錄: hello ├── manage.py ├── hello │ ├─

Git學習筆記遠程庫GitHub協同開發,fork忽略特殊文件

tex 情況 learn 多人 版本管理 獲得 logs 秘鑰 多個 遠程庫   遠程庫,通俗的講就是不再本地的git倉庫!他的工作方式和我們本地的一樣,但是要使用他就需要先建立連接!   遠程庫有兩種,一個是自己搭建的git服務器;另一種就是使用GitHub,這個網站就是

jQuery學習筆記

對象 idt 命名空間 goto div hid 右鍵 func 切換 jQuery中的事件和動畫 jquery中的事件 加載DOM 兩者等價但有細微區別 $(document).ready(function(){//編寫代碼}) 在DOM完全就緒時就可以被調用。

《EFFECTIVEC++》學習筆記

ict lsp alq list dict baidu vsr .com 學習筆記 REDIS%E6%BA%90%E7%A0%81%E5%89%96%E6%9E%90-DICT%E9%81%8D%E5%8E%86%E7%AE%97%E6%B3%95 http://mp3.

學習筆記——數據庫命令的應用

cal 名稱 nbsp ges bsp tex 密碼 連接字符串 集合 學習筆記(三)——數據庫命令的應用 一、存儲過程 (一)基本概念 存儲過程就是固化SQL數據庫系統內部的SQL語句,這樣做的好處是可以提高執行效率,提高數據庫的安全性,減

Hibernate學習筆記 --- 映射枚舉類型

enume rto 希望 enum 類名 賦值 rom cart org 對於枚舉類型,不能通過org.hibernate.annotations.Type註解來簡單的映射對應的數據庫字段類型(除非自定義類型)。對此,Hibernate提供了javax.persis

C#可擴展編程之MEF學習筆記:導出類的方法屬性

學習 說了 如何 mod ati dem ont num imp 前面說完了導入和導出的幾種方法,如果大家細心的話會註意到前面我們導出的都是類,那麽方法和屬性能不能導出呢???答案是肯定的,下面就來說下MEF是如何導出方法和屬性的。   還是前面的代碼,第二篇中已經提供了下

【轉載】.NET Remoting學習筆記信道

star fig cati 服務端 pro net string spa 處理類型 目錄 .NET Remoting學習筆記(一)概念 .NET Remoting學習筆記(二)激活方式 .NET Remoting學習筆記(三)信道 參考:♂風車車.Net .NET Fra