Warshall‘s algorithm 演算法的實現及優化(修改版)
用 Warshall’s 演算法計算傳遞閉包
- 離散數學定義:
t® = R u R^2 u R^3 u… 其中R^(n+1) = R^n 複合 R
矩陣表示:
M(R) = M + M^2 + M^3 +…+M^n(其中加為邏輯加)
所以我們只要按照這個公式每次更新M,最後的Mn就是傳遞閉包。
- Warshall演算法:
(1)置新矩陣A=M;
(2)i=1;
(3)對所有j如果A[j,i]=1,則對k=1,2,…,n,A[j,k]=A[j,k]∨A[i,k];
(4)i加1;(i是行,j是列)
(5)如果i≤n,則轉到步驟3),否則停止。
- 時間複雜度為:O(nnn)
- 用R的無窮閉包時間複雜度為O(nnn*(n - 1))
對於每個相通的j - > i,我們可以從這個相通關係出發,看看能不能通過這條相通的j - > i,更新一下j - >k。對所有的可通關係都更新一遍M,最後的結果就是傳遞閉包。
實現及優化:
下面展示一些 經典程式碼片
。
void computeAPSP(const int n) {
/* calculate shortest paths from every vertex to every vertex */
for (int k = 0; k < n; k++)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
a[i][j] = min( a[i][j], a[i][k] + a[k][j] );
}
}
}
}
利用矩陣的對稱性優化:
void computeAPSP(const int n)
{
for (int k = 0; k < n; k++)
{
for (int i = 0; i < n; i++)
{
if (k != i)
{
const int a_ki = (k < i) ? a[i][k] : a[k][i];
for (int j = 0; j < min(k, i); j++)
a[i][j] = min( a[i][j], a_ki + a[k][j] );
for (int j = k + 1; j < i; j++)
a[i][j] = min( a[i][j], a_ki + a[j][k] );
}
}
}
}
只使用矩陣的下三角部分進行優化:
void computeAPSP(const int n)
{
for (int k = 0; k < n; k++)
{
for (int i = 0; i < n; i++)
{
if (k != i)
{
const int a_ki = (k < i) ? a[i][k] : a[k][i];
for (int j = 0; j < min(k, i); j++)
a[i][j] = min( a[i][j], a_ki + a[k][j] );
for (int j = k + 1; j < i; j++)
a[i][j] = min( a[i][j], a_ki + a[j][k] );
}
}
}
}
跳過不存在的路徑的優化:
void computeAPSP(const int n)
{
for (int k = 0; k < n; k++)
{
for (int i = 0; i < n; i++)
{
if (k != i)
{
const int a_ki = (k < i) ? a[i][k] : a[k][i];
// skip if no path
if (a_ki == POSITIVE_INFINITY) continue;
for (int j = 0; j < min(k, i); j++)
a[i][j] = min( a[i][j], a_ki + a[k][j] );
for (int j = k + 1; j < i; j++)
a[i][j] = min( a[i][j], a_ki + a[j][k] );
}
}
}
}
避免大量呼叫數學函式進行優化:
void computeAPSP(const int n)
{
for (int k = 0; k < n; k++)
{
for (int i = 0; i < n; i++)
{
if (k != i)
{
const int a_ki = (k < i) ? a[i][k] : a[k][i];
// skip if no path
if (a_ki == POSITIVE_INFINITY) continue;
for (int j = 0; j < min(k, i); j++)
{
const int s_kj = a_ki + a[k][j];
if( s_kj < a[i][j] ) a[i][j] = s_kj;
}
for (int j = k + 1; j < i; j++)
{
const int s_jk = a_ki + a[j][k];
if( s_jk < a[i][j] ) a[i][j] = s_jk;
}
}
}
}
}
相關文章
- 簡單的量子演算法(二):Simon's Algorithm演算法Go
- 圖解選擇排序及演算法優化(Java實現)圖解排序演算法優化Java
- 圖解氣泡排序及演算法優化(Java實現)圖解排序演算法優化Java
- consistent hash 原理,優化及實現優化
- synchronized實現原理及鎖優化synchronized優化
- 優化演算法(五)—人工蜂群演算法Artificial Bee Colony Algorithm(ABC)優化演算法Go
- Elasticsearch在Hdfs上build的實現及優化ElasticsearchUI優化
- 選擇排序-演算法及優化排序演算法優化
- 粒子群優化演算法對BP神經網路優化 Matlab實現優化演算法神經網路Matlab
- 深析filemap.js——關於JS的演算法及優化的實踐JS演算法優化
- 智慧優化演算法——python實現免疫遺傳演算法的影像擬合優化演算法Python
- Python中的單例模式的幾種實現方式的及優化Python單例模式優化
- 差分進化演算法介紹及matlab實現演算法Matlab
- Synchronized的實現原理以及優化synchronized優化
- 演算法之路 - Way to Algorithm演算法Go
- 【Algorithm】全排列演算法Go演算法
- 網站效能優化實戰——從12.67s到1.06s的故事網站優化
- Hive使用Calcite CBO優化流程及SQL優化實戰Hive優化SQL
- Svm演算法原理及實現演算法
- WebRTC 架構優化及實踐Web架構優化
- 萬級K8s叢集背後etcd穩定性及效能優化實踐K8S優化
- Flink on K8s 在京東的持續優化實踐K8S優化
- sku演算法介紹及實現演算法
- 優化三維空間定位法及C語言快捷實現優化C語言
- Android 基於zxing的二維碼掃描功能的簡單實現及優化Android優化
- 宜信DBA實踐|全面解析Oracle等待事件的分類、發現及優化Oracle事件優化
- 棧的模擬實現及常見演算法演算法
- 如何更好的使用OPcache實現效能優化opcache優化
- Eloquent 的 whereHas 採用 where in 實現的優化優化
- Elastic-Job的執行原理及優化實踐AST優化
- Algorithm-sort 排序演算法 pythonGo排序演算法Python
- 字串演算法(string_algorithm)字串演算法Go
- 使用Let’s Encrypt實現網站https化網站HTTP
- Java高階程式設計——MySQL索引實現及優化原理解析Java程式設計MySql索引優化
- 蟻群演算法原理及Matlab實現演算法Matlab
- JS-BFA演算法及ui實現JS演算法UI
- CRC演算法原理、推導及實現演算法
- dijkstra and A* search 演算法心得及JS實現演算法JS