最近,我读了this,并对工会和时间的复杂性感到惊讶。只有路径压缩的查找算法为O((m+n) log n)
,其中m
是“查找”查询的数量,n
是“合并”查询的数量。
我对这种复杂性很感兴趣,(因为我通常在没有等级的情况下实现这个算法,即使我按照等级倒置应用了union,性能也不错!)并试图找到一个可以使时间复杂化的例子。但是由于路径压缩的强大功能,它真的很难......
是否有任何示例可以实现Omega((m+n) log n)
,或者这种复杂性只是理论,不实用?
答案 0 :(得分:6)
是的,由于Michael J. Fischer in 1972,有一个匹配的下限(见第3节)。他的例子使用了深度log n的二叉树,其中深度为0的二叉树是单个节点,深度为k的二叉树是两个深度为k-1的二叉树,其中一个根指向另一个的根。 。通过反复将二叉树的根的并集指向单例并在最深的节点上执行查找,我们执行一个昂贵的(对数步骤)操作,使另一个嵌入的二叉树被利用。
Python演示:这会打印(k+1) * 2**k
,其中k
是example
的参数,表示O(2**k)
键上O(2**k)
操作的近似操作计数。< / p>
p = {}
def find(a):
global count
b = a
while (b in p):
count += 1
b = p[b]
while (a in p):
pa = p[a]
p[a] = b
a = pa
return b
def union(a, b):
p[find(a)] = find(b)
def deepest():
maxd = (0, None)
for (a, pa) in p.items():
d = 1
while (pa in p):
d += 1
pa = p[pa]
maxd = max(maxd, (d, a))
return maxd[1]
def example(k):
global count, p
count = 0
p.clear()
for a in range(((2 ** k) - 1), 0, (- 1)):
union(a, (a & (a - 1)))
r = 0
for a in range((2 ** k), (2 ** (k + 1))):
union(r, a)
find(deepest())
r = a
example(9)
print(count)
答案 1 :(得分:2)
或者这种复杂性只是理论上的,而不是实际的吗?
是。 算法的complexity是一个纯粹的理论构造,用于描述如何算法为不同的输入大小进行扩展(在这种情况下) ,发现和工会的数量。)
这并不能保证输入的特定实例所需的步骤数(例如:5
查找和3
联合) - 除了有限之外, 当然。事实上,big O notation使用任意大乘法常数的概念,这无助于计算精确的运行时间,但足以区分complexity classes中的算法。