アルゴリズム概論 - 整列アルゴリズム(2) - 整列アル リズム(2) クイ クソ

クイ クソ ト
クイックソート

分割統治法 の考え方に基づく整列アルゴリズム

アルゴリズム概論
- 整列アル
整列アルゴリズム(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