1 / 74

クイックソートと オーダー記法

クイックソートと オーダー記法. 第 12 講 : 平成 20 年 12 月 18 日 ( 金 ) 4 限 E252 教室. 今日の講義の内容. 整列アルゴリズム クイックソートの復習 オーダー記法の復習. 整列(ソーティング)問題とは. ソーティング: Sorting ,整列,並べ替え n 個のデータ列をある基準に従って 順に並べ替える処理 昇順ソート( Ascending Sort ) 単調増加に整列(小さいもの順に整列) 一般的にソートといえばこちらを指す 降順ソート( Descending Sort ) 単調減少に整列(大きいもの順に整列)

mahdis
Download Presentation

クイックソートと オーダー記法

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. クイックソートとオーダー記法 第12講: 平成20年12月18日 (金) 4限 E252教室

  2. 今日の講義の内容 • 整列アルゴリズム • クイックソートの復習 • オーダー記法の復習 第12講 クイックソートとオーダー記法

  3. 整列(ソーティング)問題とは • ソーティング: Sorting,整列,並べ替え • n個のデータ列をある基準に従って順に並べ替える処理 • 昇順ソート(Ascending Sort) • 単調増加に整列(小さいもの順に整列) • 一般的にソートといえばこちらを指す • 降順ソート(Descending Sort) • 単調減少に整列(大きいもの順に整列) • 昇順と降順は比較に用いる不等号を逆にする • ソーティングにおける時間計算量は比較の回数を基準として考える • if 文を用いた大小比較 第12講 クイックソートとオーダー記法

  4. 整列問題の分類 • 安定性 • 安定ソート • ソートの際,同等なデータには元の並び順が保存されているソート法 例) 元々学籍番号順に並んでいたデータをその成績順にソートしたとき,同じ点数の生徒は学籍番号順に並んでいるようなソート法 • 記憶領域 • 外部ソート • ソートの際,定数個より多くの外部記憶領域を必要とするソート法 例) 現在操作中の配列の他に,その長さに応じた別のデータ格納用の配列が必要なソート法 • 内部ソート • ソートの際,定数個の記憶領域で十分なソート法 例)現在操作中の配列の内部の入れ替えだけで十分なソート法 第12講 クイックソートとオーダー記法

  5. 準備 • 入力は長さ nの数値の列 • {a1, a2, a3, a4, … , an} で表す • 数値の大小関係には推移律が成り立つ • a < bで b < cなら a < c • Swap 手続き • 配列中の 2 つの要素の値を入れ替える手続き • 実際には以下のようにテンポラリ(一時的)の変数を準備して入れ替えする swap (a, b) { temp ← a ; a ← b ; b ← temp ; } 第12講 クイックソートとオーダー記法

  6. クイックソート • クイックソート:Quick Sort • Charles A. R. Hoare が考案 • 内部ソートでは最も速いアルゴリズム • 平均計算量:O(n log n) 第12講 クイックソートとオーダー記法

  7. クイックソート: 概要 • アルゴリズム • 基準値 a*を選ぶ • 基準値 a*以下のデータを左側,残りを右側に分割 • 分割された 2 つの部分に同様の操作を,分割部分の要素数が 1 になるまで繰り返す • 再帰アルゴリズムで実装(しない方法もある) • 分割統治法: Divide and Conquer a* a* a*以下のデータ a*以上のデータ 第12講 クイックソートとオーダー記法

  8. クイックソート: 概念図 a* a* 以下のデータ a* 以上のデータ b* a* c* x < b* b* > x x < c* c* < x e* f* c* g* b* a* d* 整列済みデータ 第12講 クイックソートとオーダー記法

  9. クイックソート: partition手続き • 基準値(ピボット)によってデータを 2 つの部分に分割 • partition( a* , left , right ) • 手順 • 基準値を a[right]とする(簡単のため) • 左から走査し基準値より大きい要素を探索: 位置 i • 右から走査し基準値より小さい要素を探索: 位置 j • 両者の位置関係が i < jならば交換 • i≧jとなるまで繰り返す a[left] a[right] 第12講 クイックソートとオーダー記法

  10. 10 8 5 7 9 2 6 3 1 4 1 8 5 7 9 2 6 3 10 4 1 3 5 7 9 2 6 8 10 4 クイックソート: partition手続き a* j i j i a* < 6なので飛ばす i j 1 3 2 7 9 5 6 8 10 4 j i どんどん飛ばして 最後は a*と交換 1 3 2 4 9 5 6 8 10 7 i 第12講 クイックソートとオーダー記法

  11. 10 8 5 7 9 2 6 3 1 4 クイックソート: partition手続き a* 右端の値 a[right]を a*として採用 第12講 クイックソートとオーダー記法

  12. 10 8 5 7 9 2 6 3 1 4 クイックソート: partition手続き a* i a[i] > a*なる iを探索たまたま 1 つ目で当たる 第12講 クイックソートとオーダー記法

  13. 10 8 5 7 9 2 6 3 1 4 クイックソート: partition手続き a* j i a[j] < a*なる jを探索 またもや 1 つ目で当たる 第12講 クイックソートとオーダー記法

  14. 10 8 5 7 9 2 6 3 1 4 1 8 5 7 9 2 6 3 10 4 クイックソート: partition手続き a* j i というわけで交換 第12講 クイックソートとオーダー記法

  15. 10 8 5 7 9 2 6 3 1 4 1 8 5 7 9 2 6 3 10 4 クイックソート: partition手続き a* j i i a[i] > a*なる iを探索 次から探していることに注意 第12講 クイックソートとオーダー記法

  16. 10 8 5 7 9 2 6 3 1 4 1 8 5 7 9 2 6 3 10 4 クイックソート: partition手続き a* j i j i a[j] < a*なる jを探索 こちらも同様 第12講 クイックソートとオーダー記法

  17. 10 8 5 7 9 2 6 3 1 4 1 8 5 7 9 2 6 3 10 4 1 3 5 7 9 2 6 8 10 4 クイックソート: partition手続き a* j i j i 見つかったので交換 第12講 クイックソートとオーダー記法

  18. 10 8 5 7 9 2 6 3 1 4 1 8 5 7 9 2 6 3 10 4 1 3 5 7 9 2 6 8 10 4 クイックソート: partition手続き a* j i j i i a[i] > a*なる iを探索 第12講 クイックソートとオーダー記法

  19. 10 8 5 7 9 2 6 3 1 4 1 8 5 7 9 2 6 3 10 4 1 3 5 7 9 2 6 8 10 4 クイックソート: partition手続き a* j i j i i j a[j] < a*なる jを探索 これは条件に当てはまらない 第12講 クイックソートとオーダー記法

  20. 10 8 5 7 9 2 6 3 1 4 1 8 5 7 9 2 6 3 10 4 1 3 5 7 9 2 6 8 10 4 クイックソート: partition手続き a* j i j i i j 見つかるまでずらす ここで見つかった ただし終了条件に注意 第12講 クイックソートとオーダー記法

  21. 10 8 5 7 9 2 6 3 1 4 1 8 5 7 9 2 6 3 10 4 1 3 5 7 9 2 6 8 10 4 クイックソート: partition手続き a* j i j i i j 1 3 2 7 9 5 6 8 10 4 交換 第12講 クイックソートとオーダー記法

  22. 10 8 5 7 9 2 6 3 1 4 1 8 5 7 9 2 6 3 10 4 1 3 5 7 9 2 6 8 10 4 クイックソート: partition手続き a* j i j i i j 1 3 2 7 9 5 6 8 10 4 i a[i] > a*なる iを探索 第12講 クイックソートとオーダー記法

  23. 10 8 5 7 9 2 6 3 1 4 1 8 5 7 9 2 6 3 10 4 1 3 5 7 9 2 6 8 10 4 クイックソート: partition手続き a* j i j i i j 1 3 2 7 9 5 6 8 10 4 j i 最後まで見つからないこともある!      a[j] < a*なる jを探索 見つかったけれど j < i 第12講 クイックソートとオーダー記法

  24. 10 8 5 7 9 2 6 3 1 4 1 8 5 7 9 2 6 3 10 4 1 3 5 7 9 2 6 8 10 4 クイックソート: partition手続き a* j i j i i j 分割完了! 1 3 2 7 9 5 6 8 10 4 j i 最後なので a*と交換 1 3 2 4 9 5 6 8 10 7 i 第12講 クイックソートとオーダー記法

  25. 1 3 2 4 9 5 6 8 10 7 まず左から 左 1 2 3 4 9 5 6 8 10 7 再帰はスタックを 利用することに注意!さらに左から 左 1 2 3 4 9 5 6 8 10 7 右 といっても長さが 1 なので即座に終了 1 2 3 4 9 5 6 8 10 7 右 1 2 3 4 9 5 6 8 10 7 即座終了が発生したらやっと右 右 1 2 3 4 9 5 6 8 10 7 クイックソート 左右で再帰的に クイックソートを行う 1 3 2 4 9 5 6 8 10 7 第12講 クイックソートとオーダー記法

  26. 小の配列,基準値,大の配列の順でつなぎ合わせる小の配列,基準値,大の配列の順でつなぎ合わせる 2 3 1 4 10 8 5 7 9 6 • 外部に長さ n に比例した記憶領域が必要(マージソートと同じ欠点) 何故こんなややこしい交換をするのか • 内部ソートにするため • 外部ソートにしていいなら,もう少し簡単 基準値より大きいか小さいかで 2 つの配列を用意し,前から順番に振り分ける 10 8 5 7 9 2 6 3 1 4 基準値より小さい値用配列 2 3 1 基準値より大きい値用配列 10 8 5 7 9 6 第12講 クイックソートとオーダー記法

  27. クイックソート: 計算量 • 最良の場合 • 基準値によって左側の列と右側の列が半分に別れていくとき • 再帰の繰り返しは log n回 • 全体は O(n log n) • 最悪の場合 • 基準値が最大値,または最小値のとき • 列の大きさが 1 つずつしか減っていかない • 再帰の繰り返しは n回 • 全体は O(n2) 第12講 クイックソートとオーダー記法

  28. クイックソート: 高速化の知恵 • 基準値(ピボット)の選び方 • 今までは右端の値(a[right])を基準値にしたが,三数値を取って(a[left],a[(left+right)/2],a[right]),その真ん中の値を基準値 a*に採用 • こうすると最悪の状況になる可能性が小さくなる • 規模が小さい等,クイックサーチが不適であることがわかれば挿入法にスイッチ(そのほうが早い) 第12講 クイックソートとオーダー記法

  29. クイックソートのまとめ • 平均計算量 O(n log n) • 最悪計算量 O(n2) • 安定ソートではない • 整列されていない列でのデータの入れ替えでは元の順番が保存されない • 内部ソート • 外部記憶を必要としない • 最悪計算量は悪いが,実際の使用状況では最速のソーティングアルゴリズム (マージソートより速い) • さまざまなところで使用されている 第12講 クイックソートとオーダー記法

  30. 整列問題の計算量の下限 • いままで勉強した整列アルゴリズム • 大きく分けて O(n2)のアルゴリズムと O(n log n)のアルゴリズム • O(n log n)より早いアルゴリズムはあるか? • ないなら,既に2つの O(n log n)のアルゴリズム(マージソートとクイックソート)は勉強したので問題ない • あるなら,最も早いアルゴリズムも勉強せねばならない・・・・というか知りたいよね? 第12講 クイックソートとオーダー記法

  31. [8] [5] [7] [9] [2] [6] [3] [1] [4] [0] 1 2 3 4 5 6 7 8 9 10 整列問題の計算量の下限の証明 • 並べ替える問題=元の要素を適切に置き換える問題 • 配列の添字を並べ替えて,配列の内容を整列させる • 添字の並べ方は 10×9×8×…×2×1=10! 通り • つまり n!通り(nの階乗)の組合せのうち,正解は 1 通り • ここで,n! = O(nn)であることがわかっている [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] 10 8 5 7 9 2 6 3 1 4 第12講 クイックソートとオーダー記法

  32. 整列問題の計算量の下限の証明 • if 文では2つに分岐できる =場合の数を半分に減らせる • m回 if 文で判定すると 2mの組合せを分けられる • n! 通りの組合せから正解の 1 つを選ぶには最低でも 2m=O(nn)回の比較が必要 • 両辺を底が 2 の対数を取るとlog2 2m = m = O(log2nn) = O(nlogn) • つまり,比較回数 mは少なくとも O(nlogn) • よって,最良の計算量は O(nlogn) 第12講 クイックソートとオーダー記法

  33. アルゴリズムのオーダー • f (n)のオーダーである:O( f (n) )と書く • ある正定数 c ,n0が存在し,n0 <nである nに対して常に g(n)< c・f (n) が成立するならg(n) = O( f(n) )である • 実行時間が関数 f(n)の増加率を超えない 係数は考えない (cはいくらでも良い) c・f (n) 実際の計算量 g (n) n n0 第12講 クイックソートとオーダー記法

  34. オーダーの見積もり • 計算量のオーダー表現: • きわめて大雑把な評価尺度 • 大雑把な見積もりで導出することができる • アルゴリズムを小さな操作単位に分割 • 各操作単位のオーダーを評価 • 操作単位のオーダーを合成して,全体のオーダーを得る 第12講 クイックソートとオーダー記法

  35. アルゴリズムの分割 search(key) /* 配列 perm の中から値 key の位置を探す */ int key; { int i = 0; while (i < MAX) { if (perm[i] == key) return(i); i++; } return(-1); } 実行時間が入力サイズに依存しないステップ (基本ステップ) ループ回数が入力サイズに依存するループ構造

  36. オーダーの評価 (1) • ルール 1:基本ステップのオーダーは O(1) • 基本ステップ • 実行時間が入力サイズに依存しないステップ • 変数への代入 • 数値の演算 • ポインタ操作 etc. • 一般に,以下は基本ステップでないことに注意 • (入力サイズに依存した)配列のコピー • 関数呼び出し

  37. オーダーの評価 (2) • ルール 2: O(f(n)) の操作と O(g(n)) の操作を連続して行う場合,操作全体のオーダーは O(max(f(n), g(n))) O(f(n)) O(max(f(n), g(n))) O(g(n)) ただし,関数の大小比較は増加率により行う 1 < log n < n < n log n < n2 < n3 < … 2n

  38. オーダーの評価 (3) • ルール 3: O(f(n)) 回だけまわるループの内部で O(g(n)) の操作を実行する場合,全体のオーダーは O(f(n) × g(n)) O(f(n)) 回ループ O(f(n) × g(n)) O(g(n)) • 係数は無視してよい • 最高次の項以外は無視してよい

  39. ポイント (1/3) • 係数は無視する • 2n→n,3n→n,10n2→n2,5logn→logn • 足し算は足し算でなくなる • O(n)+O(n) → O(n+n) → O(2n) → O(n) • O(1)+O(1) → O(1+1) → O(2) → O(1) 仮に元の係数が 100 だとしても,定数 cはいくらでも大きく決められるので,cを 100 倍にすれば問題ない 係数と増加率は関係ない(係数大きくしても関数の増加率は変わらない) 第12講 クイックソートとオーダー記法

  40. ポイント (2/3) • 次数の大きい項だけ残す • n2+n → n2,n3+100n2 → n3,n + n log n → n log n • 足し算すると次数の低い項は消える • O(n2)+O(n) → O(n2+n) → O(n2) • O(n2)+O(n2)+O(n3)+O(n2) → O(n3+3n2) → O(n3) -5 -25 n2+10nというのは n2+10n+25-25=(n+5)2-25であり, n2のグラフをただ x軸方向に -5, y軸方向に -25 ずらしただけ つまり増加率は n2となんら変わらないので 10nは無視できる 無限に大きな nを考えてみよう (例えば n = 100000000000000000000000000) そうすれば -5 も -25 もほとんど増加率的には無意味 第12講 クイックソートとオーダー記法

  41. ポイント (2/3) • ループは掛け算 • O(n)×O(n2) → O(n×n2) → O(n3) • 括弧の中の計算は先にやっておく • O(n)×{O(1)+O(n)} → O(n)×{O(n)} → O(n2) 内側から順番に計算していくとややこしくない 必ず 1 つの掛け算になる O(n) × {O(n) × {{O(1) + O(n)} × {O(1) + (1)}}} も括弧を1 つずつ外していけばやさしい 第12講 クイックソートとオーダー記法

  42. オーダー評価の例 search(key) /* 配列 perm の中から値 key の位置を探す */ int key; { int i = 0; while (i < MAX) { if (perm[i] == key) return(i); i++; } return(-1); } O(1) O(n) O(1) O(n) O(n) O(1) O(1) O(1) O(1) ループの回数: 平均時,最悪時とも O(n) ⇒ 平均時間計算量,最大時間計算量とも O(n)

  43. O(1) O(n) O(1) O(1)×O(n) = O(n) O(1) O(1) 全体は O(1) + O(n) + O(1) = O(n) 練習問題 1 • 以下の手続きのオーダーを求めよ void maxmin(int a[], int n) { int i, max, min; max = min = a[0]; for (i = 1; i < n - 1; i++){ if (max < a[i]) max = a[i]; if (min > a[i]) min = a[i]; } printf(“%d, %d\n”, max, min); }

  44. O(1) O(n) O(1)×O(n) = O(n) O(1) O(n) O(1)×O(n) = O(n) O(1) O(1) 全体は O(1) + O(n) + O(n) + O(1) = O(n) 練習問題 2 • 以下の手続きのオーダーを求めよ void maxmin2(int a[], int n) { int i, max, min; max = min = a[0]; for (i = 1; i < n - 1; i++) if (max < a[i]) max = a[i]; for (i = 1; i < n - 1; i++) if (min > a[i]) min = a[i]; printf(“%d, %d\n”, max, min); }

  45. O(n)×O(n) = O(n2) O(n) O(1)×O(n) = O(n) O(n) O(1) 全体は O(n2) 練習問題 3 • 以下の手続きのオーダーを求めよ void bubble(int a[], int n) { int i, j, t; for (i = 0; i < n - 1; i++) for (j = n - 1; j > i; j--) if (a[j – 1] > a[j]) { t = a[j]; a[j] = a[j – 1]; a[j – 1] = t; } }

  46. オーダー評価:特殊ケース 1 • 条件分岐部の評価には要注意 if (x % 2 == 0) O(f(n))の処理 else O(g(n))の処理 計算量は O(max(f(n), g(n))) if (x % 2 == 3) O(f(n))の処理 else O(g(n))の処理 計算量は O(g(n)) 表現上の構造にとらわれず,実質的な振舞いの把握が必要

  47. オーダー記法に用いる関数 • n,nlogn,n2,n3: nの多項式 • 多項式時間アルゴリズム • Polynomial Time Algorithm • 現実的 • 2n,n!,nn: nの指数関数 • 指数時間アルゴリズム • Exponential Time Algorithm • 非現実的

  48. 多項式オーダーと指数オーダー • 計算速度向上の効果

  49. 再帰アルゴリズム • 処理手順が自身を用いて定義されているもの recursive (n) { if (自明なケース) { 自明なケースの処理 ; /* 終了条件 */ } else { recursive (m) ; /* m < n */ (処理) ; } } • 自身の引数より小さな引数で自身を呼び出す • 自明なケースの処理が存在 • 表面的にループが出現しない

  50. 再帰プログラムの例: 階乗の計算 • 階乗 • 例: 6! = 5×4×3×2×1 • ヒント • 6!=6×5!,5!=5×4!,・・・,2!=2×1!,1!=1 • プログラム int fact (int n) { int m; if(n = 1) return(1); else{ m = fact(n-1); return(n × m); } } ちょっとフローチャートでは書けない

More Related