Dijkstra蒜法 C語言實現(鄰接表)

2021-09-25 10:46:14 字數 1923 閱讀 1337

dijstra,求解單源最短路徑問題,解決乙個頂點到其它所有頂點的最短路徑,但是無法求解權值為負數的情況(負權值可考慮使用spfa)。是一種基於bfs(廣度優先)從起點開始,一層層向外拓展,逐步更新資料,直到拓展到終點為止。

初始有s,u兩個集合,s記錄已經求出最小值的頂點,u記錄還未求出最小值的頂點,dist陣列記錄頂點到其餘所有點的最短路徑長度,path陣列用來記錄最短路徑。。

初始時,s中只包含源點u,然後從u中找到離s中的點,最短的一條邊,(注意,此時s中的點不一定只有源點,是找s中的點與u中的點隨機組合中權值最小的那個邊)然後將這條邊對應的u中的頂點加入s,並更新與u中頂點相關的路徑。重複操作,直到遍歷圖中所有頂點都加入s中。

(1)初始化:s中只包含源點u,u中包含除源點外的所有點,dist中與u相連的邊如,dist[v]設定為的權值(dist[u] = 0, 其餘未連線的頂點的dist設定為inf,即無窮大),path[u] = v(其它未連線的點path均設定為-1)。

(2)從s中選擇乙個頂點s,u中選擇乙個頂點p,使得是最小的,然後將u中的p加入到s中。

(3)更新s中的點的最短距離,即更新dist, path陣列,(注意dist,陣列中記錄的最短路徑長度和path陣列中記錄的最短路徑都是當前條件下的最短路徑,並非全域性的最短路徑,隨著u中新頂點的不斷加入,不斷更新dist,path中的最短路徑,當遍歷完圖中所有頂點,得到的就是源點到其它頂點的最短路徑)。

更新方法:因為是我們找到的最短的那條邊,所以我們只需要判斷的權值與+ 的權值哪個更小,若新加入的p使得源點u到頂點v的距離縮短了,即**(+ ) < ()**,那麼我們就更新dist,path中關於v的資料。

(4)迴圈重複(2),(3)的操作,直到u中所有的頂點都加入到s中。

話不多說,上**

typedef struct anode arcnode;             //邊結點的型別

typedef struct vnode vnode; //頭節點型別

typedef struct adjgraph; //鄰接表

void dijkstra(adjgraph g, int u, int v)  //初始化三個陣列

p = g.adjlist[u].firstarc;

while (p != null)

s[u] = 1; path[u] = 0;

for (i = 0; i < g.n - 1; i++)

} s[w] = 1;

p = g.adjlist[w].firstarc;

while (p != null)

}p = p->nextarc;

} display(u, v

}

上面的演算法完成後,dist陣列中儲存了最短路徑長度,例如的最短路徑為2,dist[v] = 2, 但是要想得到最短路徑,需要path陣列的幫助,path中儲存了最短路徑的前驅結點,例如還是最短路徑為u -> a -> b -> c -> v,那麼path中依次為path[v] = c,path[c = b,path[b] = a,path[a] = u,path[u] = -1。

void display(int u, int v,  int *path)  //依照前驅結點關係,path_dijkstra[0]中儲存的是倒序路徑,需要得到其正序

for (i = d; i > 0; i--)

path_dijkstra[1][d - i] = path_dijkstra[0][i - 1];//path_dijkstra[1]記錄正序最短路徑

cntdijkstra = d + 1;

}

一些max,inf的巨集定義可由讀者自行設定,這裡並未給出,筆者能力有限,若有缺漏,還請指出。

Dijkstra演算法 c語言實現

dijkstra 迪傑斯特拉 演算法是典型的最短路徑路由演算法,用於計算乙個節點到其他所有節點的最短路徑。主要特點是以起始點為中心向外層層擴充套件,直到擴充套件到終點為止。dijkstra演算法 能得出最短路徑的最優解,但由於它遍歷計算的節點很多,所以效率低。dijkstra演算法是很有代表性的最短...

SPFA蒜法(SLF與LLL優化) C語言實現

dijkstra演算法可以較快的解決單源最短路徑問題,並且spfa演算法時間複雜度更大,那我們為什麼還要用spfa呢,在有些問題中,權值是有負值的情況,但是dijkstra不能解決負權值,這時候就需要我們用spfa演算法了。spfa本質上算是bellman ford的優化,由於bellman for...

C語言實現分治法

我用了大約三種方法實現,逐漸減少時間複雜度,分別用不同的命名 方式來區分他們,順便列印了那個子區間的和值最大,maxsum 1 用陣列的方式實現三次遍歷,求出所有子串行的和值,並且比較大小,求出最大子串行值 maxsum 2 用另乙個陣列來儲存從下標0開始的所有和值,然後操作次此序列,用減的方式,來...