回 2-3 道 2 データ構造とアルゴリズム
クイックソートは、
読み終えたらクイックソートが
この頁の流れ
半分に
並べ替えを 速く するには、 何を 変えればよいか
速く
前の
この
クイックソートは
クイックソートと マージソートは どう動くのか
クイックソートは
マージソートは 割って混ぜる
マージソートは、
混ぜる
割る
クイックソートは 基準で 左右に分ける
クイックソートは、
基準と
同じ
ここまでの
動かす 配列の中で入れ替えて分ける
▶ 実行ボタンを押すと結果がここに表示されます
実行すると、次の通りに出ます
[2, 3, 1, 5, 9, 8, 6] 基準 5
[1, 3, 2, 5, 9, 8, 6] 基準 1
[1, 2, 3, 5, 9, 8, 6] 基準 2
[1, 2, 3, 5, 6, 8, 9] 基準 6
[1, 2, 3, 5, 6, 8, 9] 基準 9
入れ替えた回数 71 行目で、
2 つの 違いを 表で比べる
| 見る所 | マージ | クイック |
|---|---|---|
| 平均の計算量 | O(n log n) | O(n log n) |
| 最悪の計算量 | O(n log n) | O(n²) |
| 余分に使う場所 | n 個分 | 平均 O(log n)、 |
| 同じ値の順 | 守る | 崩す |
計算量は、
動かして確かめる
1 本目は、[6, 2, 8, 3, 9, 1, 5] を、
動かす 基準で左右に分ける様子
▶ 実行ボタンを押すと結果がここに表示されます
実行すると、次の通りに出ます
[2, 3, 1, 5] 6 [8, 9]
[1] 2 [3, 5]
[] 3 [5]
[] 8 [9]
[1, 2, 3, 5, 6, 8, 9]最初は[2, 3, 1, 5] と [8, 9] に[1, 2, 3, 5, 6, 8, 9] が
2 本目は、sorted と
動かす マージとクイックの回数を数える
▶ 実行ボタンを押すと結果がここに表示されます
実行すると、次の通りに出ます
件数 マージ クイック 目安
1000 8723 11336 9966
2000 19416 27556 21932
4000 42860 56109 47863
正しく並んだ True1,000 件では、
この
クイックソートは どこで 遅くなるのか
クイックソートは、
並んだ データを 渡すと 最悪になる
先頭を
次の
動かす 並んだデータで遅くなる
▶ 実行ボタンを押すと結果がここに表示されます
実行すると、次の通りに出ます
件数 比べた回数 深さ
100 混ぜた 616 11
100 並んだ 4950 100
200 混ぜた 1708 16
200 並んだ 19900 200
400 混ぜた 4320 20
400 並んだ 79800 400400 件で、
深さがRecursionError で
基準の 選び方と、 分け方で直す
基準の
次の
動かす 基準の選び方で直す
▶ 実行ボタンを押すと結果がここに表示されます
実行すると、次の通りに出ます
並んだ
first 79800 400
middle 2698 9
med3 2698 9
3分割 2698 9
逆順
first 79800 400
middle 2698 9
med3 2698 9
3分割 2698 9
全部同じ
first 79800 400
middle 79800 400
med3 79800 400
3分割 399 2並んだ
全部が
真ん中や
そこで、
動かす 乱数で基準を選ぶ
▶ 実行ボタンを押すと結果がここに表示されます
実行すると、次の通りに出ます
並んだ 3690 18
逆順 4438 24
全部同じ 79800 400並んだ
クイックソートは 仕事で どう 確かめるのか
仕事では、
- Python の
sortedとsortは、公式文書に よると 安定な ソートで、 Timsort という マージソートの 仲間を 使っている。 クイックソートではない - C++ の
std::sortは、C++11 からの 決まりで、 最悪でも O(n log n) 回の 比べで 並べる ことが 求められている。 同じ値の 順を 守りたいときは std::stable_sortを使う - 自分で
書いた 分けて 解く 処理は、 並んだ、 逆順、 全部同じ、の 3 つの データを 必ず 試験に 入れる。 上の コードの 通り、 この 3 つが 最悪を 呼びやすい - 件数を
2 倍に して、 回数か 時間が 約 4 倍に なったら、 基準の 偏りを疑う
最悪を呼ぶ並びを試験に入れる
def test_bad_inputs():
n = 400
up = list(range(n))
for a in [up, up[::-1],
[7] * n]:
got = my_sort(a)
assert got == sorted(a)関わる実例
C++ の 決まりが、 最悪で 2 乗の ソートを 許さなくした (2007年8月30日に提起)
C++ のsort() の
一覧の
崩れた
出典は LWG Issue 713, sort() complexity is too lax (C++ 標準化委員会の
JavaScript の V8 が クイックソートを やめた (2018年9月28日)
2018年9月28日、Array.prototype.sort の
ブログは、
崩れた
よくある問い
クイックソートの 計算量は いくつですか
平均は
クイックソートは なぜ速いと 言われるのですか
基準で
クイックソートは 安定ですか
ふつうの
一番速い ソートは どれですか
どの
クイックソートは 誰が 考えましたか
C. A. R. Hoare (トニー・ホーア) です。
確認クイズ
答えだと
1 問目
先頭の
2 問目
全部が
3 問目
並び方に
4 問目
このcnt は、
比べた回数を数える
def cnt(a):
# 先頭を基準に比べた回数
if len(a) <= 1:
return 0
pv = a[0]
L = [v for v in a[1:]
if v < pv]
R = [v for v in a[1:]
if v >= pv]
return (len(a) - 1
+ cnt(L) + cnt(R))
print(cnt([1, 2, 3, 4, 5]))説明課題
先頭の
自分の
この回の 先の一歩
並べ替えの
もっと深く
この
一次資料
どれも
- LWG Issue 713, sort() complexity is too lax (C++ 標準化委員会の
不具合の 一覧、英語)。2007年8月30日に 出された こと、 それまでの 決まりが 平均で およそ N log N 回の 比べで 最悪の 決まりが 無かった こと、 3 つの 中央値の クイックソートを 許すためだった こと、 意地の 悪い 入力で 2 乗に なる こと、 決まりを O(N log N) に 改める 提案、 1997年の イントロソート - C++ の
sort の 頁 (cppreference、英語)。 std::sortがO(N log N) 回の 比べである こと、 C++98 では 平均だけの 決まりだったのが 最悪の 決まりに 変わった こと、 同じ値の 順を守る std::stable_sortがあること - Getting things sorted in V8 (V8 公式ブログ、英語)。2018年9月28日の
公開、 以前の クイックソートの 基準の 選び方と 10 個より 短い 配列の 挿入ソート、 その場で 並べられる 利点、 安定でない こと、 最悪で O(n²) に 落ちる こと、 安定な ソートを 求める 要望が 最も 古い ものの 1 つだった こと、 Timsort への 切り 替えと v7.0 と Chrome 70、 Timsort が 最悪で O(n log n) で 並んだ列は O(n) のこと - Sorting Techniques (Python 公式文書、英語)。Python の
ソートが 安定だと 保証されている こと、 Timsort を 使っていること - Quicksort, C. A. R. Hoare (The Computer Journal 5 巻 1 号 10〜16 頁、
1962年、 Oxford Academic、英語)。考えた 人が Hoare である こと、 1962年の 論文の 題と 載った 雑誌、 計算機の 記憶の 中で 並べる 新しい 方法として、 速さ、 記憶の 節約、 書きやすさで ほかの 方法より 優れていると 書いていること - Time complexity of operations on built-in types (Python 公式文書、英語)。リストの
sortがO(n log n) であること
次へ
道 2 データ構造とアルゴリズムの回
- 2-0アルゴリズムとは順次、
分岐、 反復の 3 つで書く手順頁で読む - 2-1線形探索と二分探索100 万件でも
20 回で見つかる頁で読む - 2-2バブルソートと
挿入・選択ソート遅い ソート 3 つ、 2 倍で 約 4 倍頁で読む - 2-3クイックソートと
マージソート速い ソート 2 つ、 平均と最悪この回 - 2-4スタックとキュー積む順と並ぶ順頁で読む
- 2-5再帰自分を
呼んで 小さくする頁で読む - 2-6木と
二分探索木たどる 順、片寄り頁で読む - 2-7ハッシュテーブル鍵から
一気に 引く、衝突頁で読む - 2-8ダイクストラ法と最短経路点と
線、 幅優先、 重みのある道頁で読む - 2-9動的計画法同じ
計算を 2 度しない頁で読む - 2-10試験と
面接で確かめる基本情報 科目B、 道場 10 問、 面接 20 問頁で読む
