Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonで実装する反復型(非再帰)クイックソートのプログラム

この記事では、次の問題に対する解決策をPythonのコードとともに詳しく解説します。

問題の概要

問題文: 与えられた配列を、クイックソートの考え方を利用して反復的(非再帰的)な手法でソートします。

通常、クイックソートは再帰呼び出しによって実装されることが多いですが、ここでは明示的にスタックを使用することで、再帰なしに同じアルゴリズムを実現します。まず配列をパーティション(分割)し、その各部分を個別にソートしていくことで、最終的に全体がソートされた配列を得ます。

アルゴリズムの流れ

  1. ソート対象の範囲(開始インデックス l と終了インデックス h)をスタックにプッシュする。
  2. スタックが空になるまで、範囲をポップしてはパーティション関数でピボットを正しい位置に配置する。
  3. ピボットの左側・右側に未ソートの要素が残っていれば、その範囲を再度スタックにプッシュする。
  4. これを繰り返すことで、再帰を使わずに配列全体をソートする。

実装例

# 反復的な方法
def partition(arr,l,h):
    i = ( l - 1 )
    x = arr[h]
    for j in range(l , h):
        if arr[j] <= x:
            # インクリメント
            i = i+1
            arr[i],arr[j] = arr[j],arr[i]
    arr[i+1],arr[h] = arr[h],arr[i+1]
    return (i+1)
# ソート
def quickSortIterative(arr,l,h):
    # スタックの作成
    size = h - l + 1
    stack = [0] * (size)
    # 初期化
    top = -1
    # 初期値をプッシュ
    top = top + 1
    stack[top] = l
    top = top + 1
    stack[top] = h
    # スタックからポップ
    while top >= 0:
        # ポップ
        h = stack[top]
        top = top - 1
        l = stack[top]
        top = top - 1
        # ピボット要素を正しい位置に設定
        p = partition( arr, l, h )
        # 左側の要素
        if p-1 > l:
            top = top + 1
            stack[top] = l
            top = top + 1
            stack[top] = p - 1
        # 右側の要素
        if p+1 < h:
            top = top + 1
            stack[top] = p + 1
            top = top + 1
            stack[top] = h
# メイン処理
arr = [2,5,3,8,6,5,4,7]
n = len(arr)
quickSortIterative(arr, 0, n-1)
print ("Sorted array is:")
for i in range(n):
    print (arr[i],end=" ")

実行結果

Sorted array is
2 3 4 5 5 6 7 8

上記の例では、初期配列 [2, 5, 3, 8, 6, 5, 4, 7] が正しく昇順にソートされていることが確認できます。

すべての変数はローカルスコープ内で宣言されており、それぞれの参照関係は図のようになっています。パーティション関数は配列の末尾の要素をピボットとして選択し、ピボットより小さい要素を左側に集めることで、ピボットを最終的な正しい位置へ移動させます。

計算量について

この反復型クイックソートの時間計算量は、一般的なクイックソートと同様に平均で O(n log n)、最悪ケース(すでにソート済みの配列など)では O(n²) となります。一方で、再帰呼び出しを行わないため、深い再帰によるコールスタックのオーバーフローを心配する必要がなく、メモリ使用量もスタック配列のサイズ分だけで抑えられるという利点があります。

まとめ

この記事では、Pythonを使って再帰呼び出しに頼らない反復型クイックソートを実装する方法を学びました。スタックを明示的に管理することで、再帰版と同じロジックを安全かつ効率的に実現できる点は、大規模データや再帰深度の制限がある環境で特に有用です。

  1. Pythonで選択ソートを実装する方法|仕組みとサンプルコードをわかりやすく解説

    この記事では、選択ソート(Selection Sort)の基本的な仕組みと、Python 3.x(およびそれ以前のバージョン)での実装方法について解説します。 選択ソートとは 選択ソートは、ソートされていない部分から最小の要素を繰り返し見つけ出し、先頭側へ移動させることで配列全体を整列していくアルゴリズムです。処理の過程で、対象の配列は次の2つの部分配列に分けられます。 すでにソートが完了している部分配列 まだソートされていない部分配列 選択ソートの各イテレーションでは、未ソートの部分配列から最小要素を取り出し、ソート済みの部分配列の末尾に追加していきます。 アルゴリズムの動作イメー

  2. Pythonで学ぶ挿入ソート(Insertion Sort)の仕組みと実装方法

    この記事では、Python 3.xにおける挿入ソート(Insertion Sort)の基本的な考え方と、実際のコードによる実装方法をわかりやすく解説します。 挿入ソートのアルゴリズム 挿入ソートは、配列を「整列済みの部分」と「未整列の部分」に分け、未整列の要素を一つずつ取り出して、整列済み部分の正しい位置に挿入していくシンプルなソート手法です。処理の手順は以下の通りです。 1. 各反復ごとに整列済みの配列を少しずつ拡大しながら、入力要素を走査する。 2. 現在の要素(キー)を、整列済み配列内の最大値と比較する。 3. キーがその最大値より大きければ、要素はそのままの位置に置かれ、 次の要