Pythonのクイックソートのサンプル
Pythonのクイックソートのサンプルコード
def quick_sort(arr): # arrが空か、1つの要素しかない場合は、そのまま返す if len(arr) <= 1: return arr # 基準値を決める pivot = arr[0] # 基準値より小さい要素を格納する配列 left = [] # 基準値より大きい要素を格納する配列 right = [] # 基準値を除いた要素を左右に分ける for i in range(1, len(arr)): if arr[i] < pivot: left.append(arr[i]) else: right.append(arr[i]) # 左右の要素を再帰的にクイックソートする left = quick_sort(left) right = quick_sort(right) # 左右の要素と基準値を結合して、結果を返す return left + [pivot] + right # クイックソートを実行する arr = [3, 5, 1, 2, 6, 4] print(quick_sort(arr)) # [1, 2, 3, 4, 5, 6]
コードを実行するとこうなります。
[1, 2, 3, 4, 5, 6]
上記のコードでは、基準値を配列の先頭から決めています。実際には、任意の要素を基準値として使用することもできます。また、このコードは、配列が昇順で並んでいる場合に最適な動作をしますが、降順の場合や、ランダムな並びの場合には効率が悪くなる可能性があります。
さらに、上記のコードでは、再帰的にクイックソートを実行していますが、再帰的にない実装も可能です。また、上記のコードでは、クイックソートを実行するための関数だけを記述していますが、実際には、その関数を使用するプログラム全体を記述する必要があります。
Pythonのクイックソートのアルゴリズム解説
上記のコードを見ながら、クイックソートのアルゴリズムを見ていきましょう。
まず、quick_sort()関数が定義されています。この関数は、引数として与えられた配列をクイックソートして、その結果を返します。
配列が空か、要素が1つしかない場合は、そのまま返すようにしています。これは、クイックソートが成立するための前提条件です。
次に、基準値を決めます。このサンプルコードでは、配列の先頭から基準値を決めています。
基準値より小さい要素を格納する配列 left と、基準値より大きい要素を格納する配列 right を定義します。
そして、基準値を除いた配列をfor文を使って巡回します。各要素が基準値より小さいか、大きいかを判定し、それぞれ left と right に追加します。
左側と右側の要素それぞれを再帰的にクイックソートするようにしています。これにより、左側と右側の要素をそれぞれ昇順に並び替えます。
最後に、左側、基準値、右側を結合して、結果を返します。これにより、全体として昇順に並び替えられた配列が返されます。
最後に、上記の関数を使用して、クイックソートを実行するプログラム例が示されています。このプログラムでは、配列 arr を作成し、それをクイックソートするようにしています。
実行すると、配列 arr の要素が昇順に並び替えられた状態で出力されます。
このように、Pythonでクイックソートを実装することができます。
改良を加えるなら、例えば、基準値を選ぶ方法を工夫することで、降順やランダムな配列でもより効率的な処理が可能になります。また、再帰的な実装の他に、再帰を使用しない実装も可能です。
さらに、実際には、クイックソートを行うプログラム全体を記述する必要があります。そのため、入力の受け取り方や、結果の出力方法など、さらなる改良が必要となるでしょう。
また、ソートのような処理は、exe化することで高速化が見込めます。
関連 pythonのexe化
Pythonのクイックソートは、組み込みライブラリsortedでも実現できる
Pythonには組み込みの関数 sorted()
があります。この関数は、与えられた配列を昇順に並び替えることができます。また、この関数は、配列の内容が昇順である場合には、高速に動作する実装を使用します。
ただし、この関数は、配列が降順やランダムな並びの場合には、効率が悪くなる可能性があります。また、この関数は、配列を昇順に並び替えるだけであり、任意の順序に並び替えることはできません。
sortedを使ったサンプルコードはこう。ソート対象のデータサイズが小さいときは差がわからないので、100万件のデータの昇順と降順の実行時間を表示するようにしてみました。
$ cat quick.py #!/usr/bin/python3 import time import random # 100万個の要素を持つ配列を作成する arr = [i for i in range(1000000)] # 配列をランダムに並び替える random.shuffle(arr) # 配列を昇順に並び替える start = time.time() sorted_arr = sorted(arr) end = time.time() print("昇順ソート実行時間: ", end - start) # 配列を降順に並び替える start = time.time() sorted_arr = sorted(arr, reverse=True) end = time.time() print("降順実行時間: ", end - start)
実行するとこうなります。
$ ./quick.py 昇順ソート実行時間: 1.0260288715362549 降順実行時間: 1.0419926643371582
100万件でも、0.02秒程度の差。相当な巨大データをソートする場合でなければ、気にしなくていいのかも。上記は、Intel Coreの2CPU(2.13GHz)の古いパソコンで実行した結果です。
Pythonのクイックソートのまとめ
- Pythonのクイックソートは、関数定義して再帰的呼び出しすることで実装が可能
- 組み込み関数sortedを使っての実装が簡単。しかし、昇順以外のソートは効率が悪くなる
- しかし、100万件のソートでも0.02秒程度の差なのでデータ量によっては気にしなくて良いかも。