1.Dijkstra算法的基本實現 \(O(n^2)\)
簡介:
Dijkstra算法是從一個頂點到其余各頂點的最短路徑算法,解決的是有權圖中最短路徑問題。迪傑斯特拉算法主要特點是從起始點開始,采用貪心算法的策略,每次遍歷到始點距離最近且未訪問過的頂點的鄰接節點,直到擴展到終點為止。
算法介紹推薦文章:
假設有圖G:
則G的帶權鄰接矩陣為:
matrix = [
[99, 2, 99, 6, 99, 9, 99, 99],
[99, 99, 30, 1, 99, 99, 99, 99],
[99, 99, 99, 99, 99, 99, 99, 5],
[99, 99, 99, 99, 2, 99, 99, 99],
[99, 99, 8, 99, 99, 99, 7, 99],
[99, 99, 99, 99, 3, 99, 24, 99],
[99, 99, 99, 99, 99, 99, 99, 21],
[99, 99, 99, 99, 99, 99, 99, 99]]
則時間復雜度為\(O\left( n^2 \right)\)的算法如下圖(python語言):
n = len(matrix) # 計算頂點數量
# v記錄是否訪問
# dis為起始結點到相鄰結點的距離
v = [0]*n
dis = matrix[0].copy()
# 起始情況
v[0] = 1
dis[0] = 99
# 循環n次
for _ in range(n):
# 找出與集合相鄰且距離起點最近的點
k = 0
for j in range(n):
if v[j] == 0 and dis[j] < dis[k]:
k = j
# 該點被訪問
v[k] = 1
# 用該點進行松弛(relax)
for j in range(n):
if v[j] == 0 and dis[k] + matrix[k][j] < dis[j]:
dis[j] = dis[k] + matrix[k][j]
結果:
dis = [99, 2, 13, 3, 5, 9, 12, 18]
2.從別的地方抄的虛假的和算法導論格式一樣的堆優化實現
class Graph:
def __init__(self):
self.V = []
self.w = {}
class Vertex:
def __init__(self, x):
self.key = x
self.color = 'white'
self.d = 10000
self.pi = None
self.adj = []
class Solution():
def InitializeSingleSource(self, G, s):
for v in G.V:
v.d = 10000
v.pi = None
s.d = 0
def Relax(self, u, v, w):
if v.d > u.d + w[(u, v)]:
v.d = u.d + w[(u, v)]
v.pi = u
def Dijkstra(self, G, w, s):
self.InitializeSingleSource(G, s)
S = set()
Q = G.V[:]
while Q:
u = self.ExtractMin(Q, S)
S.add(u)
for v in u.adj:
self.Relax(u, v, w)
def ExtractMin(self, Q, S):
Q.sort(key=lambda v: v.d)
return Q.pop(0)
if __name__ == '__main__':
s = Vertex('s')
t = Vertex('t')
y = Vertex('y')
x = Vertex('x')
z = Vertex('z')
s.adj = [t, y]
y.adj = [t, z, x]
t.adj = [x, y]
x.adj = [z]
z.adj = [x, s]
G = Graph()
G.V = [s, t, y, x, z]
G.w = {
(s,t):10,
(s,y):5,
(t,y):2,
(y,t):3,
(t,x):1,
(y,z):2,
(x,z):4,
(z,x):6,
(y,x):9,
(z,s):7
}
m = Solution()
m.Dijkstra(G, G.w, s)
for v in G.V:
if v != s:
print v.key, v.d, v.pi.key
else:
print v.key, v.d, v.pi