クイ クソ ト クイックソート 分割統治法 の考え方に基づく整列アルゴリズム アルゴリズム概論 - 整列アル 整列アルゴリズム(2) リズム(2) - 平均時 計算量 O(n 平均時の計算量: ( log g n)) 最悪時の計算量: O(n2) 特徴 高速で最も広く使われている 計算量はデータの並びに依存 安本 慶一 慶 yasumoto[at]is.naist.jp 2 基本的な考え方 クイ クソ トの流れ クイックソートの流れ 分割統治法 STEP1:与えられた配列の基準値を選ぶ STEP2:配列内の要素を一つずつ調べて基準値以下のデ ータを配列の左側,基準値以上のデータを右側に 集める(この作業を 分割 という) STEP3:基準値以下の部分配列,基準値以上の部分配列 基 値 部 基 値 部 に対し,STEP1 を再帰的に実行 問題を幾 かの部分問題に分割し,個々の部分問 問題を幾つかの部分問題に分割し,個々の部分問 題の解から全体の解を求める手法 基準値以下 基準値以上 整列 (部分配列が要素 つになればその部分配列に対する処理は終了) (部分配列が要素一つになればその部分配列に対する処理は終了) 整列 基準値以下の部分 統合 クイックソートのアニメーション (Wikipediaから抜粋) 基準値以上の部分 基準値と同じ要素は,どちらの部分に入れてもよい 3 4 基準値の選び方 分割方法 ポイント 分割後,二つの配列が同じ長さになれば理想的 分割後, の配列が同じ長さ なれば理想的 基準値選びで計算量が増えては本末転倒 配列の左側と右側の両方から走査し,分割の条件 を満たさない要素同士を交換 分割の条件: 左側には基準値より小さい値 右側には基準値より大きい値 基準値: pivot, 左の現在地: i, 右の現在地: j とする STEP1 a[i] ≧ pivot を見つけるまで i++ を繰り返す a[j] ≦ pivot を見つけるまで j-- を繰り返す STEP2 i ≦ j ならば a[i] と a[j] を交換し i++, j-- とする STEP3 i > j になるまで,STEP1-2を繰り返す 1)) 先頭 先頭の要素(a[1])を選ぶ 要素( [ ])を選ぶ → 簡単だが分割後の配列長さは偏るかも 2) 中央値(n/2番目に小さい値)を選ぶ → 探索が必要だが分割後の配列は同じ長さに 探索が必要だが分割後 配列は同じ長さ 3) 3つの値 (例えば a[1], a[n/2], a[n]) の中央値を選ぶ → 1) より精度がよく,2)より高速 より精度がよく 2)より高速 j i 5 分割方法 分割の実行例 配列の左側と右側の両方から走査し,分割の条件 を満たさない要素同士を交換 6 分割の条件: 左側には基準値より小さい値 右側には基準値より大きい値 基準値: pivot, 左の現在地: i, 右の現在地: j とする STEP1 a[i] ≧ pivot を見つけるまで i++ を繰り返す a[j] ≦ pivot を見つけるまで j-- を繰り返す STEP2 i ≦ j ならば a[i] と a[j] を交換し i++, j-- とする STEP3 i > j になるまで,STEP1-2を繰り返す i 基準値 pivot = 18 の場合 STEP1 a[i] ≧ 18 を見つけるまで i++ を繰り返す a[j] ≦ 18 を見つけるまで j-- を繰り返す STEP2 i ≦ j ならば a[i] と a[j] を交換し i++, j-- とする i=0 j=6 40 3 74 18 13 87 32 j 7 8 分割の実行例 分割の実行例 基準値 pivot = 18 の場合 STEP1 a[i] ≧ 18 を見つけるまで i++ を繰り返す a[j] ≦ 18 を見つけるまで j-- を繰り返す STEP2 i ≦ j ならば a[i] と a[j] を交換し i++, j-- とする 基準値 pivot = 18 の場合 STEP1 a[i] ≧ 18 を見つけるまで i++ を繰り返す a[j] ≦ 18 を見つけるまで j-- を繰り返す STEP2 i ≦ j ならば a[i] と a[j] を交換し i++, j-- とする j=4 i=0 40 3 74 18 13 87 32 40 3 i 1 i=1 13 3 入替 74 18 13 j=3 87 32 74 18 40 87 32 9 分割の実行例 10 分割の実行例 基準値 pivot = 18 の場合 STEP1 a[i] ≧ 18 を見つけるまで i++ を繰り返す a[j] ≦ 18 を見つけるまで j-- を繰り返す STEP2 i ≦ j ならば a[i] と a[j] を交換し i++, j-- とする 40 3 74 ii=2 2 18 13 3 74 18 jj=3 3 基準値 pivot = 18 の場合 STEP1 a[i] ≧ 18 を見つけるまで i++ を繰り返す a[j] ≦ 18 を見つけるまで j-- を繰り返す STEP2 i ≦ j ならば a[i] と a[j] を交換し i++, j-- とする 13 87 32 40 3 74 18 13 87 32 40 87 32 13 3 74 j=2 18 40 i=3 87 32 13 3 74 40 87 32 入替 11 18 重なるか逆転すれば終了 交差した場所の左側部分が基準値以下の値, 右側部分が基準値以上の値となる 12 演習問題 クイックソート クイ クソ ト 演習問題 クイックソート クイ クソ ト Pivot=16 i 次の配列a をクイックソートで整列する際の各ステップで の i, j の位置と分割後の配列を書きなさい.ただし,基準 値は a[(left+right) /2]を採用するものとする. を採用するも とする 7 3 22 42 4 54 30 16 9 5 赤i:pivot以上(左から探索) 青j:pivot以下(右から探索) 紫:交差 (i=j) 赤塗り潰し:確定 1 47 53 6 j 7 3 22 42 4 54 30 16 9 5 1 47 53 6 28 7 3 6 42 4 54 30 16 9 5 1 47 53 22 28 7 3 6 1 4 54 30 16 9 5 42 47 53 22 28 7 3 6 1 4 5 30 16 9 54 42 47 53 22 28 7 3 6 1 4 5 9 16 30 54 42 47 53 22 28 28 Pivot=1 7 3 6 1 4 5 9 16 30 54 42 47 53 22 28 7 3 6 1 4 5 9 16 30 54 42 47 53 22 28 1 3 6 7 4 5 9 16 30 54 42 47 53 22 28 13 演習問題 クイックソート クイ クソ ト Pivot=7 i 赤i:pivot以上(左から探索) 青j:pivot以下(右から探索) 紫:交差 (i=j) 赤塗り潰し:確定 14 赤i:pivot以上(左から探索) 青j:pivot以下(右から探索) 紫:交差 (i=j) 赤塗り潰し:確定 Pivot=28 演習問題 クイックソート クイ クソ ト j 1 3 6 7 4 5 9 16 30 54 42 47 53 22 28 1 3 6 5 4 7 9 16 6 30 5 54 42 47 53 22 28 8 1 3 4 5 6 7 9 16 30 28 42 22 53 47 54 1 3 4 5 6 7 9 16 22 28 42 30 53 47 54 1 3 4 5 6 7 9 16 22 28 42 30 53 47 54 Pivot=6 1 3 6 5 4 7 9 16 30 54 42 47 53 22 28 1 3 4 5 6 7 9 16 30 54 42 47 53 22 28 ・ ・ Pivot=42 Pivot=47 1 i Pivot=47 3 4 5 6 7 9 j 1 3 4 5 6 7 9 16 30 54 42 47 53 22 28 1 3 4 5 6 7 9 16 30 28 42 47 53 22 54 1 3 4 5 6 7 9 16 30 28 42 22 53 47 54 16 22 28 30 42 53 47 54 Pivot=53 15 1 3 4 5 6 7 9 16 22 28 30 42 47 53 54 1 3 4 5 6 7 9 16 22 28 30 42 47 53 54 16 ヒ プソ ト ヒープソート 半順序木(partial-ordered tree)を用いた整列アルゴ リズム 半順序木 計算量: O(n log n) 最悪時の計算量: O(n log n) 最悪時の計算量 半順序木を配列で実現したものを ヒープ という (プログラム内で動的に確保された領域もヒープ と呼ばれるが直接関係はない) すべての節(葉,根以外の頂点)に対して親の値 は子の値以下(or 以上) 5 9 特徴 ≠ 二分探索木 (二分探索木よりも制約が緩やか) できるだけ木の ラン が取れた状態が望まし できるだけ木のバランスが取れた状態が望ましい 15 12 データの並びによる計算量の変化が小さい デ タの並び よる計算量の変化 小さ 並列化はできず,参照の局所性も小さい 17 13 25 18 21 20 17 半順序木の構成方法 (1) 18 半順序木の構成方法 (2) 挿入の過程 (1) 初期状態 挿入の過程 (2) 7 を挿入 5 5 9 15 12 17 13 25 21 9 18 15 12 20 17 19 13 25 20 21 18 7 20 半順序木の構成方法 (3) 半順序木の構成方法 (4) 挿入の過程 (3) 親と比較し,条件が成り立たない場合は交換 挿入の過程 (4) 条件が成立するまでさらに親と比較して行く 5 5 9 15 12 17 7 25 7 18 21 12 13 20 15 17 9 25 18 21 13 20 21 半順序木からの最小要素取出し (1) 22 半順序木からの最小要素取出し(2) 最小要素(根)の削除の過程 (1) 初期状態 最小要素削除の過程 (2) 根 を取り出して最後尾の要素を持ってくる 20 5 9 12 17 13 25 9 15 21 1 15 12 18 17 20 13 25 21 18 20 5 23 24 半順序木からの最小要素取出し(3) 半順序木からの最小要素取出し(4) 最小要素削除の過程 (3) 子と比較し,条件不成立であれば小さい方と交換 最小要素削除の過程 (4) 条件が成立するまでさらに子と比較・交換を繰り返す 9 9 20 12 17 1 15 13 21 12 1 15 20 18 25 13 17 21 18 25 5 5 25 半順序木からの最小要素取出し(5) 26 配列での半順序木の表現 最小要素削除の過程 ヒープ (Heap) 1 (5) 終了 5 2 9 3 15 9 12 4 1 15 5 12 17 20 13 21 18 13 8 9 17 25 7 6 21 10 20 25 親:i , 右の子:2i+1, 左の子:2i 5 27 18 1 5 2 9 3 15 4 12 5 13 6 21 7 18 8 17 9 25 10 20 28 基本アルゴリズム ヒ プ(降順)の構築 (1) ヒープ(降順)の構築 (1) ヒープの構築 葉に近いところから再帰的にヒープを構築 未整列のリストから要素を取り出し,順にヒープに追加す る.すべての要素を追加するまで繰り返し. 1 1 (2) ヒープからのデータの取り出し 2 ヒープから最小(最大)要素を取り出し,リストに順番に書 プから最小(最大)要素を取り出 順番 書 き出す.すべての要素を取り出すまで繰り返し. 11 5 4 作業領域の節約 3 7 ヒープのための余分な領域を確保しなくて済むように,入力データ( 配列)内にヒープを構築し 配列)内にヒ プを構築し,整列結果を同じ配列に書き戻す. 整列結果を同じ配列に書き戻す 7 6 5 17 19 3 8 1. 降順(昇順)のヒープを構築する 2 最大(最小)要素を順次取り出し,配列末尾から書込む 2. 最大(最小)要素を順次取り出し 配列末尾から書込む 13 1 1 2 5 3 11 4 7 5 17 6 3 7 19 8 13 配列の中身 (入力データ) 親:i , 右の子:2i+1, 左の子:2i 29 ヒ プ(降順)の構築 (2) ヒープ(降順)の構築 30 ヒ プ(降順)の構築 (3) ヒープ(降順)の構築 葉に近いところから再帰的にヒープを構築 1 1 2 3 11 5 4 5 13 17 7 6 3 8 7 19 1 1 2 5 3 11 4 13 5 17 6 3 7 19 8 7 葉に近いところから再帰的にヒープを構築 1 1 2 3 19 5 4 5 13 17 7 6 3 8 7 配列の中身 11 1 1 2 5 3 19 4 13 5 17 6 3 7 11 8 7 配列の中身 親:i , 右の子:2i+1, 左の子:2i 親:i , 右の子:2i+1, 左の子:2i 31 32 ヒ プ(降順)の構築 (4) ヒープ(降順)の構築 ヒ プ(降順)の構築 (5) ヒープ(降順)の構築 葉に近いところから再帰的にヒープを構築 1 1 2 3 19 17 4 13 7 6 5 5 11 3 8 7 1 1 2 17 3 19 4 13 5 5 6 3 7 11 8 7 葉に近いところから再帰的にヒープを構築 1 19 2 3 1 17 4 13 7 6 5 5 11 3 8 7 1 19 2 17 3 1 4 13 5 5 6 3 7 11 8 7 配列の中身 配列の中身 親:i , 右の子:2i+1, 左の子:2i 親:i , 右の子:2i+1, 左の子:2i 33 ヒ プ(降順)の構築 (6) ヒープ(降順)の構築 34 デ データの取り出し データの取り出し(1) タの取り出し(1) タの取り出し(1) 葉に近いところから再帰的にヒープを構築 1 19 2 3 11 17 4 5 13 5 7 6 3 8 7 1 1 19 2 17 3 11 4 13 5 5 6 3 7 1 8 7 根のデータを取り出して配列末尾に書き込み 1 7 2 3 11 17 4 5 13 5 7 6 3 1 8 7 配列の中身 親:i , 右の子:2i+1, 左の子:2i 親:i , 右の子:2i+1, 左の子:2i 35 19 取出し 1 7 2 17 3 11 4 13 5 5 6 3 7 1 8 19 配列の中身 36 デ データの取り出し データの取り出し(2) タの取り出し(2) タの取り出し(2) デ データの取り出し データの取り出し(3) タの取り出し(3) タの取り出し(3) 根のデータを取り出して配列末尾に書き込み 1 17 2 3 11 7 4 13 7 6 5 5 1 3 8 1 17 2 7 3 11 4 13 5 5 6 3 7 1 8 19 根のデータを取り出して配列末尾に書き込み 1 17 2 3 11 13 4 7 7 6 5 5 1 3 1 17 2 13 3 11 4 7 5 5 6 3 7 1 8 19 配列の中身 配列の中身 親:i , 右の子:2i+1, 左の子:2i 親:i , 右の子:2i+1, 左の子:2i 37 デ データの取り出し データの取り出し(4) タの取り出し(4) タの取り出し(4) デ データの取り出し データの取り出し(5) タの取り出し(5) タの取り出し(5) 根のデータを取り出して配列末尾に書き込み 1 1 2 3 11 13 4 5 7 5 6 3 38 1 1 2 13 3 11 4 7 5 5 6 3 7 17 8 19 根のデータを取り出して配列末尾に書き込み 1 13 2 3 11 7 4 5 1 5 6 3 配列の中身 1 13 2 7 3 11 4 1 5 5 6 3 7 17 8 19 配列の中身 親:i , 右の子:2i+1, 左の子:2i 親:i , 右の子:2i+1, 左の子:2i 39 40 演習問題 ヒープ上での操作 ヒ プ上での操作 ヒ プソ トの計算量 ヒープソートの計算量 次の処理の際のヒープ上での操作を示せ (1) 7を挿入 (2) 最小要素の削除 1 5 2 9 3 15 4 12 5 13 6 21 7 18 8 8 17 9 25 10 20 基本アルゴリズム 1. すべての要素をヒープに挿入する す 要素を 挿入する 2. 最小(最大)のキーを持つデータを順に取り出す 1 の実行: 木の高さ分の繰り返し O(log n) 2 の実行: 木の高さ分の繰り返し O(log n) それぞれを要素数 n 回反復 → O(nlog n) + O(nlog n) = O(nlog n) 41 その他のソート その他のソ ト 42 バケットソート バケ トソ ト 整列アルゴリズムの分類 特定の情報量で表現可能な数(例えば1~100の整数な ど)を対象とした整列アルゴリズム 計算量: O(n) ビンソートとも呼ばれる 基本的な戦略 比較によるソート(クイックソート,ヒープソートなど) ⇒ O(n log n) が計算限界 比較によらないソート(バケットソート,基数ソートなど) 比較によらないソート(バケットソート 基数ソートなど) キーがある特定の条件を満たせば非常に高速な ソ トが可能 ソートが可能 (1) データが取りうる値すべてに対応するビンを用意 ((2)) デ データを一つずつ対応するビンに格納 タを ず 対応する ン 格納 (3) 小さい値に対応するビンから順番に中身を取り出す 43 44 バケットソート バケ トソ ト アルゴリズム (1) バケットソート バケ トソ ト アルゴリズム (2) 例: 7, 4, 2, 8, 1 をバケットソートによって整列 (1~10 (1 10 のどれかということが事前に分かっている) 例: 7, 4, 2, 8, 1 をバケットソートによって整列 (2) データを対応するビンに入れる (1) 1 1~10 10 に対応する10個のビンを用意 1 2 3 4 5 6 7 8 9 10 7 4 1 2 2 3 8 4 1 5 6 7 8 9 10 45 46 まとめ バケットソート バケ トソ ト アルゴリズム (3) 例. 7, 4, 2, 8, 1 をバケットソートによって整列 クイ クソ ト クイックソート (3) 左から順番に中身を取り出す 1 2 3 4 5 6 7 8 9 10 ヒープソート 1 2 4 7 8 半順序木を使用 最悪時計算量 O(n log n) バケットソート バケットソ ト 計算量: O(n), 分割統治法に基づいたアルゴリズム 平均計算量 O(n log n),最悪時 O(n2) 実用上は最高速 データのとる範囲が決まっている時に使用可能 計算量 記憶領域ともに O(n) 計算量,記憶領域ともに 記憶量: O(n) 47 48
© Copyright 2024 Paperzz