我一直在尝试使用Fibonacci min-heap优化我的Dijkstra算法,根据此 1 [article]该文章应采用$ O(M + N log(N))的复杂度$其中:
我已经计算了总体复杂度,但是不确定是否正确,我希望得到一些建议:
首先,我们要尽量避免使用“声明和赋值”,因为它们都是不变的基本运算,占用$ O(1)$,对我的复杂度没有贡献,因为n $ \ to $ $ \ infty $。
第一个for循环,其复杂度为$ O(N)$。
采用$ O(log(N))$的headpop方法假定我们在二进制堆中查找权重最小的节点。
这是我不确定的地方。因此,我们从源中获取权重较小的节点,然后更新邻居的标签,这意味着我们转到邻接列表(在本例中为Dictionary)并检查集合$ \ delta ^ +(v)中的所有可能边$,即从v到包含已访问节点的集合$ \ S $中的另一个顶点u的所有节点。因此完整图的整体复杂度为O(n-1)$。
记住所有这些,我最终得到:$ O(N \ cdot(log(N)+ M))$ $ equiv $ $ O(N \ cdot(log(N)+ N-1)) $ $ \ equiv $ $ O(N \ cdot log(N)+ N ^ 2)$ $ \ equiv $ $ O(N ^ 2)$对于较大的N。
这不是我希望从解决方案中获得的预期输出,因此,很高兴听到您的建议。
def dijkstra2(successors, s):
S = []; S.append(s)
n = len(successors)
L = dict(); L[s] = 0
P = dict(); P[s] = '-'
# Iterate through the V/{s}-nodes and set L[j] to infinity and P[j] to s.
for o in range(0, n):
if o != s:
L[o] = numpy.inf
P[o] = s
# Visited vector.
visited = [False] * n;
# Heapq
queue = [(0, s)];
while queue:
par_len, v = heappop(queue);
# v is unvisited
if visited[v] is False:
visited[v] = True
for w, edge_len in successors[v].items():
# Check if the child is unvisited and compute the distance.
if visited[w] is False and edge_len + par_len < L[w] :
heappush(queue, (edge_len + par_len, w))
L[w] = edge_len + par_len
P[w] = v
return L, P
答案 0 :(得分:1)
Dijkstra的算法是:
O(|E| |decrease-key(Q)| + |V| |extract-min(Q)|)
斐波那契堆:
O(|E| + |V| log |V|)
二进制堆:
O((|E| + |V|) log |V|)
E是:
|E| = O(|V|^2)
Q是: 最小优先级队列按其自身当前的距离估计值对顶点进行排序。
初始化堆:
from heapq import *
from random import randint
f = FibonacciHeap()
h = []
n = 100
for i in xrange(0, n):
r = randint(1, 1000)
f.insert(r)
heappush(h, r)
打印运行时间代码:
import time
# test fib heap running time
start_time = time.time()
while f.total_nodes > 0:
m = f.extract_min()
print "%s seconds run time for fib heap" % (time.time() - start_time)
# test heapq running time
start_time = time.time()
while h:
m = heappop(h)
print "%s seconds run time for heapq" % (time.time() - start_time)