1

サイクルソートは、ソートしている順列をサイクルに因数分解できるという考えに基づいたインプレースソートです。各サイクルを1位置回転すると、配列が並べ替えられます。これは簡単にコーディングできるため、配列への書き込み数は、インプレースソートに必要な理論上の最小値になります(これは、書き込み数を最小限に抑えたいフラッシュドライブなどの巨大なデータセットに適しています。デバイス)。

ウィキペディアのコードをインプレースソートに保ち、最適な書き込み数を維持しながら、コードの実行時間を改善する方法はありますか、それとも最高の方法ですか?

これが実装です(からに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
4

1 に答える 1

3

このアルゴリズムの高価な部分は、各アイテムがどこに行くかを把握することです。残りの部分は、一度に1サイクルずつ順列を適用するだけです。このコードは、O(n ^ 2)がアイテムの移動先を把握し、O(n)が実際にアイテムを移動するために使用します。

一時ストレージ(たとえば、フラッシュの代わりにDRAM)を使用する場合は、ポインターの一時配列を使用してそれを並べ替え、その結果を使用して実際のデータを移動することで、はるかに高速にすることができます。これは、レコードを繰り返し移動するコストが法外な場合に、大きなレコードを並べ替える方法です。

O(n lg(n))ビットの補助記憶装置を使用することが許可されていない場合は、運が悪い可能性があると思います。どの順列を実行するかを記録するには、log(n!)= O(n lg(n))ビットのストレージが必要です。したがって、順列を段階的に計算する必要があり(cycleSortのように)、それを安価に行う方法はわかりません。

于 2010-10-04T17:54:26.007 に答える