优化循环排序实现

Posted

技术标签:

【中文标题】优化循环排序实现【英文标题】:Optimizing a cycle sort implementation 【发布时间】:2010-10-04 15:24:57 【问题描述】:

循环排序是一种就地排序,它基于您正在排序的排列可以分解为循环的想法。如果您将每个循环旋转一个位置,则数组将被排序。这可以很容易地进行编码,以便对数组的写入次数是任何就地排序所需的理论最小值(这对于例如闪存驱动器上的大量数据集来说非常好,您希望在其中最大限度地减少写入次数设备)。

是否有任何方法可以提高 code on Wikipedia 的运行时间,同时保持其就地排序并保持最佳写入次数,或者它是最好的?

这里是实现(注意 range(a, b)ab - 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

【问题讨论】:

【参考方案1】:

这个算法的昂贵部分是弄清楚每件物品的去向。其余的只是一次应用一个排列一个周期。这段代码需要 O(n^2) 才能确定项目的去向,并且需要 O(n) 才能实际移动它们。

如果您愿意使用一些临时存储(例如 DRAM 而不是闪存),则可以通过使用临时指针数组、对其进行排序、然后使用结果来移动实际数据来加快速度。这就是您对大​​型记录进行排序的方式,因为重复移动它们的成本太高了。

如果不允许您拥有 O(n lg(n)) 位辅助存储,我认为您可能会不走运。仅记录要执行的排列需要 log(n!) = O(n lg(n)) 位的存储空间。因此,您需要逐步计算排列(就像 cycleSort 那样),我看不出有任何方法可以廉价地做到这一点。

【讨论】:

以上是关于优化循环排序实现的主要内容,如果未能解决你的问题,请参考以下文章

如何优化冒泡排序?

Java代码实现—冒泡排序

图解算法系列之冒泡排序(优化版)

插入排序

冒泡排序python优化版本

冒泡排序和优化