Transcript Document
コンピュータアルゴリズム2
3. 整列(ソーティング)(2)
田浦
http://www.logos.ic.i.u-tokyo.ac.jp
/~tau/lecture/software/
マージソート
考え方:
配列を何も考えずに半分に分ける
各半分ずつを(再帰的に)マージソート
整列されている2本の配列をマージ
マージするために元の配列とは別途,同じ大きさの配列が必
要
...
...
マージソート概形
void mergesort_rec(int * a, int * b, int l, int r)
/* a[l]..a[r-1]をsortしてb[l]..b[r-1]へ格納 */
{
int i;
if (r - l > 1) {
int c = (l + r) / 2;
mergesort_rec(a, b, l, c);
mergesort_rec(a, b, c, r);
b[l]...b[c-1] と b[c]... b[r-1]をマージして,
merge(b, a, l, c, r);
a[l], ..., a[r-1]に入れる
}
for (i = l; i < r; i++) { b[i] = a[i]; }
}
クイズ
マージソートの計算量は?
クイックソートと比べた利点・欠点は?
ヒープソート
面白いアルゴリズムだがここでは省略
またしてもO(n log n)
教科書を参照
O(n log n)より良い整列アルゴリズ
ムはあるか?
n 個の要素の全順序を一意に決定するのに,
2要素の大小比較(と全順序の性質)だけを使って行う
(どんなに賢い方法で比較する要素を選んだとしても)最悪で
何回必要か?
O(n log n)限界の抜け道:
大小比較以外を用いる整列法
バケットソート
条件:要素のとりうる値が小さい整数やそれと同等のデータ
用例:小さな整数や文字の整列
Radixソート(基底法)
各要素の値が,
小さな整数の少数個の組であり,
要素間の順序は小さな整数の辞書式順序で決められる
用例:32 bit整数(8 bitが4つの列とみなす),短い固定長以
下の文字列(e.g., 10文字以下の文字列)
バケットソート: 方法
仮定 : 要素の値は 0 … K – 1 の整数
0 k < K – 1の各値が配列中に何回ずつ出現するかを数え
る( count[k] : k の出現回数)
あきらかに以下が望むべき最終状態である
最初のcount[0]要素が0
0 1 0 1 0 0 0 1 2 2 1
次のcount[1]要素が1
0が7つ
次のcount[2]要素が2
1が4つ
2が2つ
...
次のcount[k-1]要素がk – 1
コーディングは自習問題とする
0 0 0 0 0 0 0 1 1 1 1
できた...
0 0
2 2
バケットソート: 計算量
空間O(K + n)
K = とりうる値の種類
時間O(K + n)
K 要素のcount配列の初期化
K << n では強いが,実用的にはほとんどの場合 n << K
8 bit整数の整列にはそのまま使えるが, 32 bitとなると??
もう一工夫 Radixソート
Radixソート: 仮定
仮定1: 各要素が,小さな整数(バケットソート可能な値)の固
定個の列
例: 32 bit整数 = 8 bit整数が4つの列とみなせる
例: 長さの限られた文字列(e.g., 人名)
仮定2: 要素の比較は列同士の「辞書式順序」.たとえば
“a1 a2 a3 a4” “b1 b2 b3 b4” iff
(a1 b1)
or (a1 = b1) and (a2 b2)
or (a1 = b1) and (a2 = b2) and (a3 b3)
or (a1 = b1) and (a2 = b2) and (a3 = b3) and (a4 b4)
適用可能例
○ 32 bit, 64 bit 符号なし整数
○ 32 bit, 64 bit符号あり整数(何に気をつけるべきか?)
○ 10文字ぴったりの文字列
○ 10文字以下の文字列(how?)
?? 浮動小数点数
浮動小数点数の表現
IEEE 754 単精度(多くのマシンでのCのfloat)の場合
(–1)s x 2e
1.0 x < 2.0, – 128 e 127
符号 = s
指数部 = e+127
仮数部 = x – 1.0
Radixソート: 方法
32 bit符号なし整数を8 bit整数 4 個の列とみなす場合を例に
取る
方法:
最下位8 bit (a(24:32))でバケットソート
次の8 bit
(a(16:24))でバケットソート
次の8 bit
(a(8:16))でバケットソート
最上位8 bit (a(0:8))でバケットソート
注:バケットソートをする際に,比べるキーの値(たとえば
a(16:24))が同じである要素の順番を保存するようにする(こ
のようにバケットソートを作ることは易しい)
なぜこれで整列ができるか?
Radixソート: 計算量
列全体でとりうる値の種類をL, 各要素が取りうる値の種類を
Kとする
空間計算量: O(K + n)
時間計算量: O((log L / log K) (K + n))