ココココココココココココ ココココココココ コココココココ ココココココココ 2 ココココココ ココ ココ ココココ ココココ ( ) コココココココココココココ ココ [email protected] http://narayama.naist.jp/~y-nakamr/ クククククククク クククククク コ 12 コ : ココ 20 コ 12 コ 18 コ ( コ ) 4 コ E252 ココ
Jan 09, 2016
コンピュータアルゴリズム大阪電気通信大学 情報通信工学部 光システム工学科 2 年次配当科目
中村 嘉隆(なかむら よしたか)奈良先端科学技術大学院大学 助教
[email protected]://narayama.naist.jp/~y-nakamr/
クイックソートとオーダー記法
第 12 講 : 平成 20 年 12 月 18 日 ( 金 ) 4 限 E252 教室
第 12 講 クイックソートとオーダー記法
今日の講義の内容
整列アルゴリズムクイックソートの復習
オーダー記法の復習
2009/12/18 2
整列(ソーティング)問題とは ソーティング: Sorting ,整列,並べ替え
n 個のデータ列をある基準に従って順に並べ替える処理
昇順ソート( Ascending Sort )単調増加に整列(小さいもの順に整列)一般的にソートといえばこちらを指す
降順ソート( Descending Sort )単調減少に整列(大きいもの順に整列)
昇順と降順は比較に用いる不等号を逆にする ソーティングにおける時間計算量は比較の回数を
基準として考える if 文を用いた大小比較
2009/12/18第 12 講 クイックソートとオーダー記
法3
整列問題の分類 安定性
安定ソートソートの際,同等なデータには元の並び順が保存されている
ソート法例) 元々学籍番号順に並んでいたデータをその成績順にソートしたと
き,同じ点数の生徒は学籍番号順に並んでいるようなソート法
記憶領域外部ソート
ソートの際,定数個より多くの外部記憶領域を必要とするソート法
例) 現在操作中の配列の他に,その長さに応じた別のデータ格納用の配列が必要なソート法
内部ソートソートの際,定数個の記憶領域で十分なソート法
例)現在操作中の配列の内部の入れ替えだけで十分なソート法2009/12/18
第 12 講 クイックソートとオーダー記法
4
準備 入力は長さ n の数値の列
{a1, a2, a3, a4, … , an} で表す 数値の大小関係には推移律が成り立つ
a < b で b < c なら a < c Swap 手続き
配列中の 2 つの要素の値を入れ替える手続き 実際には以下のようにテンポラリ(一時的)の変数を準
備して入れ替えするswap (a, b) { temp ← a ; a ← b ; b ← temp ;}
2009/12/18第 12 講 クイックソートとオーダー記
法5
第 12 講 クイックソートとオーダー記法
クイックソート
クイックソート: Quick SortCharles A. R. Hoare が考案内部ソートでは最も速いアルゴリズム平均計算量: O(n log n)
2009/12/18 6
クイックソート: 概要アルゴリズム
基準値 a* を選ぶ基準値 a* 以下のデータを左側,残りを右側に分割分割された 2 つの部分に同様の操作を,分割部分
の要素数が 1 になるまで繰り返す再帰アルゴリズムで実装(しない方法もある)分割統治法: Divide and Conquer
2009/12/18第 12 講 クイックソートとオーダー記
法
a*
a*a* 以下のデータ a* 以上のデータ7
クイックソート: 概念図
2009/12/18第 12 講 クイックソートとオーダー記
法
a*a* 以下のデータ a* 以上のデータ
a*
d*
整列済みデータ
b*
a*b*
c*
e* f* g*
x < b* b* > x x < c* c* < x
c*
8
クイックソート: partition 手続き
基準値(ピボット)によってデータを 2 つの部分に分割
partition( a* , left , right )
手順 基準値を a[right] とする(簡単のため) 左から走査し基準値より大きい要素を探索: 位置 i 右から走査し基準値より小さい要素を探索: 位置 j 両者の位置関係が i < j ならば交換i ≧ j となるまで繰り返す
2009/12/18第 12 講 クイックソートとオーダー記
法
a[right]a[left]
9
クイックソート: partition 手続き
2009/12/18第 12 講 クイックソートとオーダー記
法
1 8 5 7 9 2 6 3 10 4
1 3 5 7 9 2 6 8 10 4
1 3 2 7 9 5 6 8 10 4
1 3 2 4 9 5 6 8 10 7
10 8 5 7 9 2 6 3 1 4
a* < 6 なので飛ばす
a* < 6 なので飛ばす
どんどん飛ばして
最後は a* と交換
どんどん飛ばして
最後は a* と交換
i j
a*
i j
i j
ij
i10
クイックソート: partition 手続き
2009/12/18第 12 講 クイックソートとオーダー記
法
10 8 5 7 9 2 6 3 1 4
a*
右端の値 a[right] を a* として採用
右端の値 a[right] を a* として採用
11
クイックソート: partition 手続き
2009/12/18第 12 講 クイックソートとオーダー記
法
10 8 5 7 9 2 6 3 1 4
a*
i
a[i] > a* なる i を探索
たまたま 1 つ目で当たる
a[i] > a* なる i を探索
たまたま 1 つ目で当たる
12
クイックソート: partition 手続き
2009/12/18第 12 講 クイックソートとオーダー記
法
10 8 5 7 9 2 6 3 1 4
a*
i j
a[j] < a* なる j を探索
またもや 1 つ目で当たる
a[j] < a* なる j を探索
またもや 1 つ目で当たる
13
クイックソート: partition 手続き
2009/12/18第 12 講 クイックソートとオーダー記
法
1 8 5 7 9 2 6 3 10 4
10 8 5 7 9 2 6 3 1 4
i j
a*
というわけで交換
というわけで交換
14
クイックソート: partition 手続き
2009/12/18第 12 講 クイックソートとオーダー記
法
1 8 5 7 9 2 6 3 10 4
10 8 5 7 9 2 6 3 1 4
i j
a*
i
a[i] > a* なる i を探索
次から探していることに注意
a[i] > a* なる i を探索
次から探していることに注意
15
クイックソート: partition 手続き
2009/12/18第 12 講 クイックソートとオーダー記
法
1 8 5 7 9 2 6 3 10 4
10 8 5 7 9 2 6 3 1 4
i j
a*
i j
a[j] < a* なる j を探索
こちらも同様
a[j] < a* なる j を探索
こちらも同様
16
クイックソート: partition 手続き
2009/12/18第 12 講 クイックソートとオーダー記
法
a*
1 8 5 7 9 2 6 3 10 4
1 3 5 7 9 2 6 8 10 4
10 8 5 7 9 2 6 3 1 4
i j
i j
見つかったので交換
見つかったので交換
17
クイックソート: partition 手続き
2009/12/18第 12 講 クイックソートとオーダー記
法
a*
1 8 5 7 9 2 6 3 10 4
1 3 5 7 9 2 6 8 10 4
10 8 5 7 9 2 6 3 1 4
i j
i j
a[i] > a* なる i を探索
a[i] > a* なる i を探索
i
18
クイックソート: partition 手続き
2009/12/18第 12 講 クイックソートとオーダー記
法
a*
1 8 5 7 9 2 6 3 10 4
1 3 5 7 9 2 6 8 10 4
10 8 5 7 9 2 6 3 1 4
i j
i j
i j
a[j] < a* なる j を探索これは条件に当てはまらな
い
a[j] < a* なる j を探索これは条件に当てはまらな
い19
クイックソート: partition 手続き
2009/12/18第 12 講 クイックソートとオーダー記
法
a*
1 8 5 7 9 2 6 3 10 4
1 3 5 7 9 2 6 8 10 4
10 8 5 7 9 2 6 3 1 4
i j
i j
i j
見つかるまでずらすここで見つかった見つかるまでずらすここで見つかった
ただし終了条件に注意ただし終了条件に注意20
クイックソート: partition 手続き
2009/12/18第 12 講 クイックソートとオーダー記
法
1 8 5 7 9 2 6 3 10 4
1 3 5 7 9 2 6 8 10 4
1 3 2 7 9 5 6 8 10 4
10 8 5 7 9 2 6 3 1 4
i j
a*
i j
i j
交換交換21
クイックソート: partition 手続き
2009/12/18第 12 講 クイックソートとオーダー記
法
1 8 5 7 9 2 6 3 10 4
1 3 5 7 9 2 6 8 10 4
1 3 2 7 9 5 6 8 10 4
10 8 5 7 9 2 6 3 1 4
i j
a*
i j
i j
a[i] > a* なる i を探索
a[i] > a* なる i を探索
i
22
クイックソート: partition 手続き
2009/12/18第 12 講 クイックソートとオーダー記
法
1 8 5 7 9 2 6 3 10 4
1 3 5 7 9 2 6 8 10 4
1 3 2 7 9 5 6 8 10 4
10 8 5 7 9 2 6 3 1 4
i j
a*
i j
i j
i
a[j] < a* なる j を探索
見つかったけれど j < i
a[j] < a* なる j を探索
見つかったけれど j < i
最後まで見つからないこともある!
最後まで見つからないこともある!
j
23
クイックソート: partition 手続き
2009/12/18第 12 講 クイックソートとオーダー記
法
1 8 5 7 9 2 6 3 10 4
1 3 5 7 9 2 6 8 10 4
1 3 2 7 9 5 6 8 10 4
1 3 2 4 9 5 6 8 10 7
10 8 5 7 9 2 6 3 1 4
i j
a*
i j
i j
ij
i
最後なのでa* と交換最後なのでa* と交換
分割完了!分割完了!
24
クイックソート
2009/12/18第 12 講 クイックソートとオーダー記
法
1 3 2 4 9 5 6 8 10 7 左右で再帰的にクイックソートを
行う
左右で再帰的にクイックソートを
行う1 3 2 4 9 5 6 8 10 7まず左からまず左から
左
再帰はスタックを利用することに注意!さらに左から
再帰はスタックを利用することに注意!さらに左から
1 2 3 4 9 5 6 8 10 7
左
といっても長さが 1 なので即座に終了
といっても長さが 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 2 3 4 9 5 6 8 10 7
右
25
第 12 講 クイックソートとオーダー記法
何故こんなややこしい交換をするのか
内部ソートにするため 外部ソートにしていいなら,もう少し簡単
10 8 5 7 9 2 6 3 1 4
*a
2 3 1
10 8 5 7 9 6
基準値より大きいか小さいかで 2 つの
配列を用意し,前から順番に振り分ける
基準値より大きいか小さいかで 2 つの
配列を用意し,前から順番に振り分ける
基準値より小さい値用配列
基準値より大きい値用配列
42 3 1 10 8 5 7 9 6
小の配列,基準値,大の配列の順でつなぎ合わせる
小の配列,基準値,大の配列の順でつなぎ合わせる
•外部に長さ n に比例した記憶領域が必要(マージソートと同じ欠点)
2009/12/18 26
2009/12/18第 12 講 クイックソートとオーダー記
法
クイックソート: 計算量最良の場合
基準値によって左側の列と右側の列が半分に別れていくとき
再帰の繰り返しは log n 回全体は O(n log n)
最悪の場合基準値が最大値,または最小値のとき列の大きさが 1 つずつしか減っていかない再帰の繰り返しは n 回全体は O(n2)
27
クイックソート: 高速化の知恵
基準値(ピボット)の選び方今までは右端の値( a[right])を基準値にし
たが,三数値を取って( a[left], a[(left+right)/2], a[right]),その真ん中の値を基準値 a* に採用
こうすると最悪の状況になる可能性が小さくなる
規模が小さい等,クイックサーチが不適であることがわかれば挿入法にスイッチ(そのほうが早い)
2009/12/18第 12 講 クイックソートとオーダー記
法28
クイックソートのまとめ 平均計算量 O(n log n) 最悪計算量 O(n2) 安定ソートではない
整列されていない列でのデータの入れ替えでは元の順番が保存されない
内部ソート外部記憶を必要としない
最悪計算量は悪いが,実際の使用状況では最速のソーティングアルゴリズム (マージソートより速い)
さまざまなところで使用されている2009/12/18
第 12 講 クイックソートとオーダー記法
29
第 12 講 クイックソートとオーダー記法
整列問題の計算量の下限
いままで勉強した整列アルゴリズム大きく分けて O(n2) のアルゴリズムと O(n
log n) のアルゴリズムO(n log n) より早いアルゴリズムはある
か ?ないなら,既に 2 つの O(n log n) のアルゴ
リズム(マージソートとクイックソート)は勉強したので問題ない
あるなら,最も早いアルゴリズムも勉強せねばならない・・・・というか知りたいよね ?
2009/12/18 30
整列問題の計算量の下限の証明 並べ替える問題=元の要素を適切に置き換える問題 配列の添字を並べ替えて,配列の内容を整列させる
添字の並べ方は 10×9×8×…×2×1=10! 通り つまり n! 通り( n の階乗)の組合せのうち,正解は 1 通り
ここで, n! = O(nn) であることがわかっている
2009/12/18第 12 講 クイックソートとオーダー記
法
10 8 5 7 9 2 6 3 1 4
[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]
1 2 3 4 5 6 7 8 9 10
[8] [5] [7] [9] [2] [6] [3] [1] [4] [0]
31
整列問題の計算量の下限の証明 if 文では 2 つに分岐できる
=場合の数を半分に減らせるm 回 if 文で判定すると 2m の組合せを分け
られるn! 通りの組合せから正解の 1 つを選ぶには
最低でも 2m=O(nn) 回の比較が必要両辺を底が 2 の対数を取ると
log2 2m = m = O(log2 nn) = O(n log n)つまり,比較回数 m は少なくとも O(n log n)よって,最良の計算量は O(n log n)2009/12/18
第 12 講 クイックソートとオーダー記法
32
f (n) のオーダーである: O( f (n) ) と書くある正定数 c , n0 が存在し, n0 < n である
n に対して常に g(n) < c・ f (n) が成立するなら g(n) = O( f(n) ) である実行時間が関数 f(n) の増加率を超えない
第 12 講 クイックソートとオーダー記法
アルゴリズムのオーダー
n
c・ f (n)
実際の計算量 g (n)
係数は考えない( c はいくらで
も良い)
係数は考えない( c はいくらで
も良い)
n02009/12/18 33
オーダーの見積もり
計算量のオーダー表現: きわめて大雑把な評価尺度 大雑把な見積もりで導出することができる
1. アルゴリズムを小さな操作単位に分割2. 各操作単位のオーダーを評価3. 操作単位のオーダーを合成して,全体の
オーダーを得る
2009/12/18第 12 講 クイックソートとオーダー記
法34
アルゴリズムの分割
2009/10/9
実行時間が入力サイズに依存しないステップ(基本ステップ)ループ回数が入力サイズに依存するループ構造
search(key) /* 配列 perm の中から値 key の位置を探す*/
int key;{
int i = 0;
while (i < MAX) {if (perm[i] == key)
return(i);i++;
}return(-1);
}
オーダーの評価 (1)
ルール 1 :基本ステップのオーダーは O(1)
基本ステップ 実行時間が入力サイズに依存しないステップ
変数への代入数値の演算ポインタ操作 etc.
一般に,以下は基本ステップでないことに注意 (入力サイズに依存した)配列のコピー 関数呼び出し
2009/10/9
オーダーの評価 (2)
ルール 2 : O(f(n)) の操作と O(g(n)) の操作を連続して行う場合,操作全体のオーダーは O(max(f(n), g(n)))
2009/10/9
O(f(n))O(f(n))
O(g(n))O(g(n))O(max(f(n), g(n)))O(max(f(n), g(n)))
ただし,関数の大小比較は増加率により行う1 < log n < n < n log n < n2 < n3 < … 2n
オーダーの評価 (3)
ルール 3 : O(f(n)) 回だけまわるループの内部で O(g(n)) の操作を実行する場合,全体のオーダーは O(f(n) × g(n))
2009/10/9
O(f(n) × g(n))O(f(n) × g(n))O(f(n)) 回ループO(f(n)) 回ループ
O(g(n))O(g(n))
係数は無視してよい最高次の項以外は無視してよい
第 12 講 クイックソートとオーダー記法
ポイント (1/3)
2009/12/18 39
係数は無視する2n→n , 3n→n , 10n2→n2 , 5log n→log n足し算は足し算でなくなる
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 倍にすれば問題ない
係数と増加率は関係ない(係数大きくしても関数の増加率は変わらない)
次数の大きい項だけ残す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)
第 12 講 クイックソートとオーダー記法
ポイント (2/3)
-5
-25
2009/12/18 40
n2+10n というのは n2+10n+25-25=(n+5)2-25 であり,n2 のグラフをただ x 軸方向に -5 , y軸方向に -25 ずらしただけつまり増加率は n2 となんら変わらないので 10n は無視できる
n2+10n というのは n2+10n+25-25=(n+5)2-25 であり,n2 のグラフをただ x 軸方向に -5 , y軸方向に -25 ずらしただけつまり増加率は n2 となんら変わらないので 10n は無視できる 無限に大きな n を考えてみよう
(例えば n = 100000000000000000000000000 )そうすれば -5 も -25 もほとんど増加率的には無
意味
無限に大きな n を考えてみよう (例えば n = 100000000000000000000000000 )
そうすれば -5 も -25 もほとんど増加率的には無意味
ポイント (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 つずつ外していけばやさしい
2009/12/18第 12 講 クイックソートとオーダー記
法41
オーダー評価の例
2009/10/9
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(n)
O(1)
O(1)O(1)O(1)
O(1)
O(n)
ループの回数: 平均時,最悪時とも O(n)⇒ 平均時間計算量,最大時間計算量とも O(n)
以下の手続きのオーダーを求めよ
練習問題 1
2009/10/9
O(n)
O(1)
O(1)O(1)
O(1)
O(1)×O(n) = O(n)
全体は O(1) + O(n) + O(1) = O(n)
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);
}
練習問題 2
以下の手続きのオーダーを求めよ
2009/10/9
O(n)
O(n)
O(1)
O(1)
O(1)O(1)
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);
}
O(1)×O(n) = O(n)
O(1)×O(n) = O(n)
全体は O(1) + O(n) + O(n) + O(1) = O(n)
以下の手続きのオーダーを求めよ
O(n)
練習問題 3
2009/10/9
O(n)
O(1)
O(1)×O(n) = O(n)
O(n)×O(n) = O(n2)
全体は O(n2)
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;
}}
オーダー評価:特殊ケース 1
条件分岐部の評価には要注意
2009/10/9
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))
表現上の構造にとらわれず,実質的な振舞いの把握が必要
オーダー記法に用いる関数 n , nlogn , n2 , n3 : n の多項式
多項式時間アルゴリズムPolynomial Time Algorithm現実的
2n , n! , nn : n の指数関数指数時間アルゴリズムExponential Time Algorithm非現実的
2009/10/9
多項式オーダーと指数オーダー
計算速度向上の効果
2009/10/9
再帰アルゴリズム 処理手順が自身を用いて定義されているもの
recursive (n) { if (自明なケース ) { 自明なケースの処理 ; /* 終了条件 */ } else { recursive (m) ; /* m < n */ ( 処理 ) ; }}
自身の引数より小さな引数で自身を呼び出す自明なケースの処理が存在表面的にループが出現しない
2009/10/9
再帰プログラムの例 : 階乗の計算
階乗 例 : 6! = 5×4×3×2×1
ヒント 6! = 6×5! , 5! = 5×4! , ,・・・ 2! = 2×1! , 1! = 1
プログラム
2009/10/9
int fact (int n){ int m; if(n = 1) return(1); else{ m = fact(n-1); return(n × m); }}
ちょっとフローチャートでは書け
ない
ちょっとフローチャートでは書け
ない
再帰プログラムの概念
ちょっと分かりにくいので以下の図のように考えるとよい
2009/10/9
int fact (4){ m = fact(3); return(4 × m);}
int fact (3){ m = fact(2); return(3 × m);}
int fact (2){ m = fact(1); return(2 × m);}
int fact (1){ return(1);}
1
return(2×1);
2
return(3×2);
6
return(4×6);
fact(4)
= 24
= 4×3×2×1
ユークリッドの互除法を再帰で書く
ヒントr = 0 でないなら, m , n の最大公約数の代わりに n, r の最大公約数を求める
2009/10/9
int gcd (int m, int n){ int r; r = m % n; if(r = 0) return(n); else return( gcd(n,r) );}
r=0 なら n が 最大公約数
r=0 なら n が 最大公約数
r=0 でないなら n と r の 最大公約数を求めるr=0 でないなら n と r の 最大公約数を求める
オーダー評価:特殊ケース 2
再帰プログラムのオーダー評価は,少し面倒
2009/10/9
int recursive(int n){
if (n <= 1)return(1);
elsereturn(recursive(n – 1) + recursive(n – 1));
}
この場合のステップ数は,漸化式 Tn = 2Tn-1 で与えられる⇒ 計算量は O(2n)
(互除法は Tn = Tn-1 なので O(n) )
入力が n のときの,この再帰プログラムの計算量を Tn とする
入力が n のときの,この再帰プログラムの計算量を Tn とする
演習問題: マージソートMerge_Seq(size, from, into) { start ← 1 ; while (start < n) { i ← start ; j ← start + size ; k ← start ; iend ← min (start+size-1, n) ; jend ← min (start+2*size-1, n) ; while (i <= iend) and (j <= jend) { if (from[i] <= from[j]) { Put(i); } else { Put(j) ; } } while (i <= iend){ Put(i); } while (j <= jend) { Put(j); } start ← start+2*size; }}
2009/12/18第 12 講 クイックソートとオーダー記
法54
基本ステップと繰り返しに分類してみる
基本ステップと繰り返しに分類してみる
関数呼び出しがある関数は別々に考える
関数の中身を見てみる
関数呼び出しがある関数は別々に考える
関数の中身を見てみる
関数 Put は基本ステップのみで構成 → O(1)
関数 Put は基本ステップのみで構成 → O(1)
演習問題: マージソートメインの部分Straight_Merge_Sort { seqsize ← 1 ; while (seqsize < n) { Merge_Seq(seqsize, a, b) ; Merge_Seq(2*seqsize, b, a) ; seqsize ← 4 * seqsize ; }}
Put (index) { into[k] ← from[index] ; index ← index + 1 ; k ← k + 1 ;}2009/12/18
第 12 講 クイックソートとオーダー記法
55
演習問題: マージソート
2009/12/18第 12 講 クイックソートとオーダー記
法56
O(1) だった
O(1) だった
よって繰り返しの
内部は全て O(1)よって繰り返しの
内部は全て O(1)
Merge_Seq(size, from, into) { start ← 1 ; while (start < n) { i ← start ; j ← start + size ; k ← start ; iend ← min (start+size-1, n) ; jend ← min (start+2*size-1, n) ; while (i <= iend) and (j <= jend) { if (from[i] <= from[j]) { Put(i); } else { Put(j) ; } } while (i <= iend){ Put(i); } while (j <= jend) { Put(j); } start ← start+2*size; }}
Merge_Seq(size, from, into) { start ← 1 ; while (start < n) { i ← start ; j ← start + size ; k ← start ; iend ← min (start+size-1, n) ; jend ← min (start+2*size-1, n) ; while (i <= iend) and (j <= jend) { if (from[i] <= from[j]) { Put(i); } else { Put(j) ; } } while (i <= iend){ Put(i); } while (j <= jend) { Put(j); } start ← start+2*size; }}
演習問題: マージソート
2009/12/18第 12 講 クイックソートとオーダー記
法57
繰り返しの回数を考えてみる
繰り返しの回数を考えてみる
i の指す配列3 6 7
2 4 5 8
10
j の指す配列iend
jend
size
i と j がそれぞれ iend, jend まで繰り返す
i と j はどう増える??
i と j がそれぞれ iend, jend まで繰り返す
i と j はどう増える??Put() を見てみないとわからないなPut() を見てみないとわからないな
メインの部分Straight_Merge_Sort { seqsize ← 1 ; while (seqsize < n) { Merge_Seq(seqsize, a, b) ; Merge_Seq(2*seqsize, b, a) ; seqsize ← 4 * seqsize ; }}
Put (index) { into[k] ← from[index] ; index ← index + 1 ; k ← k + 1 ;}
演習問題: マージソート
2009/12/18第 12 講 クイックソートとオーダー記
法58
Put(index) の中では () 内の値 index を 1 増やしているPut(i) なら i を 1 増やすPut(j) なら j を 1 増やす
Put(index) の中では () 内の値 index を 1 増やしているPut(i) なら i を 1 増やすPut(j) なら j を 1 増やす
Merge_Seq(size, from, into) { start ← 1 ; while (start < n) { i ← start ; j ← start + size ; k ← start ; iend ← min (start+size-1, n) ; jend ← min (start+2*size-1, n) ; while (i <= iend) and (j <= jend) { if (from[i] <= from[j]) { Put(i); } else { Put(j) ; } } while (i <= iend){ Put(i); } while (j <= jend) { Put(j); } start ← start+2*size; }}
演習問題: マージソート
2009/12/18第 12 講 クイックソートとオーダー記
法59
繰り返しの回数を考えてみる
繰り返しの回数を考えてみる
i の指す配列3 6 7
2 4 5 8
10
j の指す配列iend
jend
size
i は start から start + size -1 までj は start + size から start + 2×size -1 まで
i は start から start + size -1 までj は start + size から start + 2×size -1 まで
つまり最大で 2×size 回まわる →
O(size)つまり最大で 2×size 回まわる →
O(size)
Merge_Seq(size, from, into) { start ← 1 ; while (start < n) { i ← start ; j ← start + size ; k ← start ; iend ← min (start+size-1, n) ; jend ← min (start+2*size-1, n) ; while (i <= iend) and (j <= jend) { if (from[i] <= from[j]) { Put(i); } else { Put(j) ; } } while (i <= iend){ Put(i); } while (j <= jend) { Put(j); } start ← start+2*size; }}
演習問題: マージソート
2009/12/18第 12 講 クイックソートとオーダー記
法60
繰り返しの回数を考えてみる
繰り返しの回数を考えてみる
i の指す配列3 6 7
2 4 5 8
10
j の指す配列iend
jend
size
それぞれ最大で size 回まわるけど,各回では,どちらかしか回らない
それぞれ最大で size 回まわるけど,各回では,どちらかしか回らない
これは上の繰り返しで余った分i の列が余ったら while(i <= iend) で, j の列が余ったら while(j <= jend) で結果の列に追加す
るための繰り返し
これは上の繰り返しで余った分i の列が余ったら while(i <= iend) で, j の列が余ったら while(j <= jend) で結果の列に追加す
るための繰り返し
Merge_Seq(size, from, into) { start ← 1 ; while (start < n) { i ← start ; j ← start + size ; k ← start ; iend ← min (start+size-1, n) ; jend ← min (start+2*size-1, n) ; while (i <= iend) and (j <= jend) { if (from[i] <= from[j]) { Put(i); } else { Put(j) ; } } while (i <= iend){ Put(i); } while (j <= jend) { Put(j); } start ← start+2*size; }}
演習問題: マージソート
2009/12/18第 12 講 クイックソートとオーダー記
法61
繰り返しの回数を考えてみる
繰り返しの回数を考えてみる
i の指す配列3 6 7
2 4 5 8
10
j の指す配列iend
jend
sizeよく考えてみると,この繰り返し 3 つ合わせて, 2×size 回しか回らな
い!
よく考えてみると,この繰り返し 3 つ合わせて, 2×size 回しか回らな
い!繰り返し内部は O(1) なので,ここ全体で O(2×size)×O(1)=O(size)
繰り返し内部は O(1) なので,ここ全体で O(2×size)×O(1)=O(size)
Merge_Seq(size, from, into) { start ← 1 ; while (start < n) { i ← start ; j ← start + size ; k ← start ; iend ← min (start+size-1, n) ; jend ← min (start+2*size-1, n) ; while (i <= iend) and (j <= jend) { if (from[i] <= from[j]) { Put(i); } else { Put(j) ; } } while (i <= iend){ Put(i); } while (j <= jend) { Put(j); } start ← start+2*size; }}
演習問題: マージソート
2009/12/18第 12 講 クイックソートとオーダー記
法62
繰り返しの回数を考えてみる
繰り返しの回数を考えてみる
i の指す配列3 6 7
2 4 5 8
10
j の指す配列iend
jend
sizestart が 1 から 2×size ずつ増えていって n を超え
るまでつまり, n/(2×size) 回→ O(n/(2size))=O(0.5n/size)=
O(n/size)
start が 1 から 2×size ずつ増えていって n を超え
るまでつまり, n/(2×size) 回→ O(n/(2size))=O(0.5n/size)=
O(n/size)
この繰り返しは何回まわ
る??
この繰り返しは何回まわ
る??
Merge_Seq(size, from, into) { start ← 1 ; while (start < n) { i ← start ; j ← start + size ; k ← start ; iend ← min (start+size-1, n) ; jend ← min (start+2*size-1, n) ; while (i <= iend) and (j <= jend) { if (from[i] <= from[j]) { Put(i); } else { Put(j) ; } } while (i <= iend){ Put(i); } while (j <= jend) { Put(j); } start ← start+2*size; }}
演習問題: マージソート
2009/12/18第 12 講 クイックソートとオーダー記
法63
O(size)
O(1)
O(1)
O(1)
O(n/size)
Merge_Seq(size, from, into) { start ← 1 ; while (start < n) { i ← start ; j ← start + size ; k ← start ; iend ← min (start+size-1, n) ; jend ← min (start+2*size-1, n) ; while (i <= iend) and (j <= jend) { if (from[i] <= from[j]) { Put(i); } else { Put(j) ; } } while (i <= iend){ Put(i); } while (j <= jend) { Put(j); } start ← start+2*size; }}
演習問題: マージソート
2009/12/18第 12 講 クイックソートとオーダー記
法64
O(1)+O(size)+O(1)=
O(size)
O(1)
O(n/size)
Merge_Seq(size, from, into) { start ← 1 ; while (start < n) { i ← start ; j ← start + size ; k ← start ; iend ← min (start+size-1, n) ; jend ← min (start+2*size-1, n) ; while (i <= iend) and (j <= jend) { if (from[i] <= from[j]) { Put(i); } else { Put(j) ; } } while (i <= iend){ Put(i); } while (j <= jend) { Put(j); } start ← start+2*size; }}
演習問題: マージソート
2009/12/18第 12 講 クイックソートとオーダー記
法65
O(size)×O(n/size) =
O(n)
O(1)
Merge_Seq(size, from, into) { start ← 1 ; while (start < n) { i ← start ; j ← start + size ; k ← start ; iend ← min (start+size-1, n) ; jend ← min (start+2*size-1, n) ; while (i <= iend) and (j <= jend) { if (from[i] <= from[j]) { Put(i); } else { Put(j) ; } } while (i <= iend){ Put(i); } while (j <= jend) { Put(j); } start ← start+2*size; }}
演習問題: マージソート
2009/12/18第 12 講 クイックソートとオーダー記
法66
O(n)+O(1) =
O(n)引数 size の値に関わらず O(n) となる
第 12 講 クイックソートとオーダー記法
演習問題: マージソート
基本ステップと繰り返しに分類してみる
基本ステップと繰り返しに分類してみる
メインの部分Straight_Merge_Sort { seqsize ← 1 ; while (seqsize < n) { Merge_Seq(seqsize, a, b) ; Merge_Seq(2*seqsize, b, a) ; seqsize ← 4 * seqsize ; }} 関数 Merge_Seq() の計算量はさっき求め
た !引数(括弧の中の値 seqsize )に関わらず
O(n)
関数 Merge_Seq() の計算量はさっき求めた !
引数(括弧の中の値 seqsize )に関わらず
O(n)2009/12/18 67
第 12 講 クイックソートとオーダー記法
演習問題: マージソート
さてこの繰り返しは何回まわる??さてこの繰り返しは何回まわる??
seqsize が 1 から繰り返し毎に 4 倍され n になるまで
seqsize が 1 から繰り返し毎に 4 倍され n になるまで
メインの部分Straight_Merge_Sort { seqsize ← 1 ; while (seqsize < n) { Merge_Seq(seqsize, a, b) ; Merge_Seq(2*seqsize, b, a) ; seqsize ← 4 * seqsize ; }}
1→4→42→43→ →・・・ 4m=n
m=log4n つまり O(log n) 回
1→4→42→43→ →・・・ 4m=n
m=log4n つまり O(log n) 回2009/12/18 68
第 12 講 クイックソートとオーダー記法
演習問題: マージソートメインの部分
Straight_Merge_Sort {
seqsize ← 1 ;
while (seqsize < n) {
Merge_Seq(seqsize, a, b) ;
Merge_Seq(2*seqsize, b, a) ;
seqsize ← 4 * seqsize ;
}
}
O(log n)
O(1)
O(1)
O(n)
O(n)
2009/12/18 69
メインの部分
Straight_Merge_Sort {
seqsize ← 1 ;
while (seqsize < n) {
Merge_Seq(seqsize, a, b) ;
Merge_Seq(2*seqsize, b, a) ;
seqsize ← 4 * seqsize ;
}
}第 12 講 クイックソートとオーダー記
法
演習問題: マージソート
2009/12/18 70
O(log n)
O(1)
O(n)+O(n)+O(1)=
O(n)
メインの部分
Straight_Merge_Sort {
seqsize ← 1 ;
while (seqsize < n) {
Merge_Seq(seqsize, a, b) ;
Merge_Seq(2*seqsize, b, a) ;
seqsize ← 4 * seqsize ;
}
}第 12 講 クイックソートとオーダー記
法
演習問題: マージソート
2009/12/18 71
O(1)
O(n)×O(log n) =
O(n log n)
メインの部分
Straight_Merge_Sort {
seqsize ← 1 ;
while (seqsize < n) {
Merge_Seq(seqsize, a, b) ;
Merge_Seq(2*seqsize, b, a) ;
seqsize ← 4 * seqsize ;
}
}第 12 講 クイックソートとオーダー記
法
演習問題: マージソート
2009/12/18 72
O(n log n)+O(1) =
O(n log n)
マージソートのオーダーは O(n log n)
第 12 講 クイックソートとオーダー記法
第 12 講のまとめ
クイックソートの復習オーダー記法の復習
2009/12/18 73
今後の予定
2010/1/8復習その 2
探索木など
2010/1/15模擬試験
2010/1/29試験
持ち込み:自筆ノート・ミニレポート,講義資料は持ち込み不可!
2009/12/18第 12 講 クイックソートとオーダー記
法74