Median を選ばず適当な位置をピボットに配列を分割する。
ワーストケースパフォーマンスを避けるために単純なランダムでないバリエーションもある。
(Median-of-three 等) 配列が小さい時は挿入ソートの方が速くなるので、 サイズが一定以下になったら挿入ソートを使う。
def selectPivotIndex(left, right): return random.randint(left, right + 1) # 配列を、pivotIndex の値で分割する。 # pivotIndex の値より小さい値は前、 # pivotIndex の値より大きい値は後ろに移動 def partition(arr, comp_func, left, right, pivotIndex): # pivot の値を最後尾に移動 pivot = arr[pivotIndex] tmp = arr[right] arr[right] = pivot arr[pivotIndex] = tmp # pivot より小さい値を前に持っていく store = left for i in range(left, right): if comp_func(arr[i], pivot) < 0: tmp = arr[i] arr[i] = arr[store] arr[store] = tmp store += 1 # pivot を配置 tmp = arr[store] arr[store] = pivot arr[right] = tmp return store # 挿入ソート def insertion(arr, comp_func, left, right): for i in range(left, right + 1): tmp = arr[i] j = i - 1 while j >= 0 and arr[j] >= tmp: arr[j + 1] = arr[j] j -= 1 arr[j + 1] = tmp # 最大深さを記録。特に意味は無い。 max_depth = 0 # 配列サイズがこれ以下なら挿入ソートを使う MIN_SIZE = 4 def qsort(arr, comp_func, left, right, depth): if right <= left: return pivotIndex = selectPivotIndex(left, right) pivotIndex = partition(arr, comp_func, left, right, pivotIndex) # サイズが一定以下なら挿入ソート if pivotIndex <= MIN_SIZE: # グローバル変数にアクセスするには global 宣言が必要 global max_depth max_depth = max(max_depth, depth) insertion(arr, comp_func, left, pivotIndex - 1) else: qsort(arr, comp, left, pivotIndex - 1, depth + 1) if right - pivotIndex - 1 <= MIN_SIZE: global max_depth max_depth = max(max_depth, depth) insertion(arr, comp_func, pivotIndex + 1, right) else: qsort(arr, comp, pivotIndex + 1, right, depth + 1) a = range(1, 500) random.shuffle(a) print a qsort(a, comp, 0, len(a) - 1, 0) print max_depth print a
0 件のコメント:
コメントを投稿