gpt4 book ai didi

python - 测试加权快速联合算法?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:17:31 25 4
gpt4 key购买 nike

我正在通过 Coursera 学习 Algorithms, Part I,并希望测试 Quick Find、Quick Union 和 Weighted Quick Union 算法的运行时间。该类(class)是用我不熟悉的 Java 编写的,所以我已经完成并尝试用我更熟悉的 Python 重新创建算法。

既然我已经实现了所有功能,我打算测试每个功能以验证运行时间/复杂性。我一直在考虑使用 timeit 库,但这似乎会引发错误的结果,例如,加权快速联合比 QuickUnion 需要更长的时间才能完成。

我如何验证加权快速联合实际上是 O(log n) 并且比快速联合更快?这是我到目前为止创建和尝试的内容:

O(N**2) - 慢

class QuickFind_Eager:
def __init__(self, nodes):
self.array = [num for num in range(nodes)]

# Joins two nodes into a component
def union(self, first_node, second_node):
for pos, val in enumerate(self.array):
if self.array[pos] == self.array[first_node]:
self.array[pos] = self.array[second_node]

# Checks if two nodes are in the same component
def connected(self, first_node, second_node):
return self.array[first_node] == self.array[second_node]

O(N) - 仍然太慢 - 避免

class QuickUnion_Lazy:
def __init__(self, nodes):
self.array = [num for num in range(nodes)]

# Follows parent pointers to actual root
def root(self, parent):
while parent != self.array[parent]:
parent = self.array[parent]
return parent

# Joins two nodes into a component
def union(self, first_node, second_node):
self.array[first_node] = self.array[second_node]

# Checks if two nodes are in the same component
def connected(self, first_node, second_node):
return self.root(first_node) == self.root(second_node)

O(log N) - 相当快

class WeightedQuickUnion:
def __init__(self, nodes):
self.array = [num for num in range(nodes)]
self.weight = [num for num in range(nodes)]

# Follows parent pointers to actual root
def root(self, parent):
while parent != self.array[parent]:
parent = self.array[parent]
return parent

# Joins two nodes into a component
def union(self, first_node, second_node):
if self.root(first_node) == self.root(second_node):
return

if (self.weight[first_node] < self.weight[second_node]):
self.array[first_node] = self.root(second_node)
self.weight[second_node] += self.weight[first_node]
else:
self.array[second_node] = self.root(first_node)
self.weight[first_node] += self.weight[second_node]

# Checks if two nodes are in the same component
def connected(self, first_node, second_node):
return self.root(first_node) == self.root(second_node)

O(N + M lg* N) - 极速

class WeightedQuickUnion_PathCompression:
def __init__(self, nodes):
self.array = [num for num in range(nodes)]
self.weight = [num for num in range(nodes)]

# Follows parent pointers to actual root
def root(self, parent):
while parent != self.array[parent]:
self.array[parent] = self.array[self.array[parent]]
parent = self.array[parent]
return parent

# Joins two nodes into a component
def union(self, first_node, second_node):
if self.root(first_node) == self.root(second_node):
return

if self.weight[first_node] < self.weight[second_node]:
self.array[first_node] = self.root(second_node)
self.weight[second_node] += self.weight[first_node]
else:
self.array[second_node] = self.root(first_node)
self.weight[first_node] += self.weight[second_node]

# Checks if two nodes are in the same component
def connected(self, first_node, second_node):
return self.root(first_node) == self.root(second_node)

测试运行时间

def test_quickfind(quickfind):
t = quickfind(100)
t.union(1,2)
t.connected(1,2)
t.union(4,2)
t.union(3,4)
t.connected(0,2)
t.connected(1,4)
t.union(0,3)
t.connected(0,4)

import timeit

t = timeit.timeit(stmt="test_quickfind(QuickFind_Eager)", setup="from __main__ import QuickFind_Eager; from __main__ import test_quickfind", number=100000)
print(t)
# 11.4380569069981
t = timeit.timeit(stmt="test_quickfind(QuickUnion_Lazy)", setup="from __main__ import QuickUnion_Lazy; from __main__ import test_quickfind", number=100000)
print(t)
# 1.4744456350017572
t = timeit.timeit(stmt="test_quickfind(WeightedQuickUnion)", setup="from __main__ import WeightedQuickUnion; from __main__ import test_quickfind", number=100000)
print(t)
# 2.738758583996969
t = timeit.timeit(stmt="test_quickfind(WeightedQuickUnion_PathCompression)", setup="from __main__ import WeightedQuickUnion_PathCompression; from __main__ import test_quickfind", number=100000)
print(t)
# 3.0113827050008695

更新添加了 timeit 的结果。

最佳答案

您需要将算法的运行时间制成表格,作为问题大小的函数,即。为不同的问题大小调用 quickfind(例如 100,200,300,400,500;请注意,预计后者对于天真的 O(n^2) 算法至少运行 3 分钟)。

您仍然不能保证您观察到渐近运行时函数(这就是 O 符号的含义:O(f) 实际上描述了一系列函数 g_i, g_i = a_i * f(n) + b_i; a_i, b_i: const [有点滥用符号]),因为您的某些实现可能会遇到资源耗尽(阅读:没有更多的 ram)导致超出您的实现范围的显着性能影响。

关于python - 测试加权快速联合算法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31186801/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com