循环排序是一种就地排序,它基于这样的想法:您排序的排列可以被分解为循环。如果将每个循环旋转一个位置,则将对数组进行排序。这可以很容易地编码,以便对阵列的写入次数是任何就地排序所需的理论最小值(这对于闪存驱动器上的大型数据集很有用,在这种情况下,您希望最大限度地减少写入次数。设备)。
是否有任何方法可以改善code on Wikipedia的运行时间,同时保持其就地排序并保持最佳写入次数,或者它是最好的?
以下是实施(请注意range(a, b)
从a
转到b - 1
):
# Sort an array in place and return the number of writes.
def cycleSort(array):
writes = 0
# Loop through the array to find cycles to rotate.
for cycleStart in range(0, len(array) - 1):
item = array[cycleStart]
# Find where to put the item.
pos = cycleStart
for i in range(cycleStart + 1, len(array)):
if array[i] < item:
pos += 1
# If the item is already there, this is not a cycle.
if pos == cycleStart:
continue
# Otherwise, put the item there or right after any duplicates.
while item == array[pos]:
pos += 1
array[pos], item = item, array[pos]
writes += 1
# Rotate the rest of the cycle.
while pos != cycleStart:
# Find where to put the item.
pos = cycleStart
for i in range(cycleStart + 1, len(array)):
if array[i] < item:
pos += 1
# Put the item there or right after any duplicates.
while item == array[pos]:
pos += 1
array[pos], item = item, array[pos]
writes += 1
return writes
答案 0 :(得分:3)
此算法的昂贵部分是确定每个项目的去向。其余部分只是一次应用一个循环的排列。这段代码需要O(n ^ 2)来确定项目的去向和O(n)实际移动它们。
如果你愿意使用一些临时存储(比如DRAM而不是闪存),你可以通过使用一个临时指针数组,对它进行排序,然后使用结果来移动实际数据来加快速度。这就是你如何对重复移动它们的成本过高的大型记录进行排序。
如果您不允许使用O(n lg(n))位辅助存储器,我想您可能会失败。只记录要进行的排列需要log(n!)= O(n lg(n))个存储位。所以你需要逐步计算排列(就像cycleSort那样),我看不出任何方法可以便宜地做到这一点。