web-dev-qa-db-ja.com

この非常に短いPythonクイックソート実装を使用する必要がありますか?

def quicksort(N):
    if len(N) < 2:
        return N
    else:
        less = quicksort([number for number in N[1:] if number < N[0]])
        more = quicksort([number for number in N[1:] if number >= N[0]])

    return sum([less, [N[0]], more], [])

print(quicksort([1, 9, 6, 10, 8, 7, 2, 4, 3, 5]))

動作しているように見えますが、他のより長い実装のバリエーションよりも技術的に適切かどうかはわかりません。

1
user232181

Pythonの組み込みのsortをご存知であり、これを学習演習として求めているだけだと思います。 (「最良の」ソートを使用したいだけの場合は、Pythonの組み込みのsort関数を使用してください。これは高度に最適化されており、Pythonで実装するものよりも高速です。)

簡単に言うと、クイックソート関数にはバグがあり、修正すれば期待どおりに機能します。ただし、考慮すべき点は他にもあります。

バグ

配列に_N[0]_に等しい要素がいくつかある場合、コードは正しく機能しません。 quicksort([1,2,1,1])を試してください。

パフォーマンス

漸近(big-O)の複雑さは標準のクイックソートと同じですが、このコードのパフォーマンスは次の理由で低下します。

  • 新しいリストの作成がたくさんあります(クイックソートは、メモリ割り当てを必要としないように簡単に設計できます)
  • リストを1回ではなく2回スキャンする

実装のタイミングを別の実装と比較してみてください(timeitモジュールを使用してください)。必ず大きな入力リストを試してください。

また、クイックソートアルゴリズムの複雑さは最悪の場合O(n2)。 O(n log n)の最悪の場合の複雑さが必要な場合は、マージソートを検討する必要があります。これは、非常に短いコードで実装することもできます。

明快さ

なぜ

_return sum([less, [N[0]], more], [])
_

あなたが簡単にできるとき:

_return less + [N[0]] + more
_

いずれの場合も、これには新しいリストの作成が含まれるため、おそらく明確さを犠牲にして、パフォーマンスをさらに向上させることができることに注意してください。

4
Artelius