アルゴリズムとデータ構造 2010年7月22日 酒居敬一([email protected]) http://www.info.kochi-tech.ac.jp/k1sakai/Lecture/ALG/2010/index.html x h(x) h(x)+g(x) 12 12 12 22 22 22 7 7 7 4 4 4 62 16 16 39 16 29 6 6 87 18 18 31 8 8 44 21 21 71 2 2 20 20 20 67 21 16+3=19 21+3=24 ハッシュ表中の位置 19 1 最小の子の数は2 最大の子の数は3 問題のB木 57を追加 7を追加 最大の子の数は3というルールがあるので、 木を根のほうに向かって成長させる。 84を削除 58を削除 最小の子の数は2というルールがあるので、 木を根のほうから刈り込む。 75を削除 マージソート (並列処理) • データの分割にかかる時間(2要素に分解) log2n - 1 • ソートにかかる時間 2n - 1 • ステップ数は (log2n + 2n – 2) つまり O(n) • 例ではn=16なので34ステップで終了 53 12 41 69 11 2 84 28 31 63 97 58 76 19 91 88 53 69 69 11 84 84 63 97 97 12 53 41 84 2 31 63 58 97 19 88 88 2 28 28 76 91 91 41 69 11 58 91 76 12 53 2 31 88 19 11 41 76 28 63 12 58 11 31 2 19 12 19 28 31 41 53 58 63 69 76 84 88 91 97 パイプラインマージソート • データの分割にかかる時間(図には書いてない) log2n - 1 • 最初のデータがソートされる時間 log2n • 引き続くn-1個のデータがソートされる時間 n-1 • ステップ数は (2 log2n + n-2) つまりO(n)である • 例では、n=16 なので22ステップで終了 ソートの計算量 n個のデータの並びは n! とおり存在する ソートとは、n! の並びのどれであるかを特定すること 1回の比較で並びの可能性が1/2にできる 並びの可能性が1以下にできればソート完了 そのときの比較回数をkとすれば、 すなわち Stirlingの公式から およそ n log nという計算量になる 比較を使う限りの性能上限 線形なデータ構造における整列 (ソート) • 比較によるもの – バブルソート – クイックソート – マージソート • 比較によらないもの – ビンソート 計算量を減らす • 比較を用いたソーティングアルゴリズム – 大小といった情報は、比較することで得られる – データの並びについては仮定をおかない – そうするとO(n log2 n)は下回れない • 比較を用いないソーティング – 情報を得なければいけない点は変わらない – データの性質に合ったアルゴリズムを使う バブルソートばかりを使うのはやめて、クイッ クソートのような性能の良いアルゴリズムを 使いましょうという話は間違ってはいない。 ただし、データの性質をも考慮に入れ てそれが最善かを考える必要はある。 分割統治法(162ページ) • 元の問題をサイズの小さいいくつかの部 分問題に分割 • 個々の部分問題を何らかの方法で解決 • それらの解を統合することで元の問題の 解を得る 比較を使わないソート ビンソート • • ビン(瓶ではない、bin = 箱)を使う データの持つ性質を利用する – 例:情報の2年生の学生番号(範囲が限られる) 1. ビンをデータの取りうる範囲分確保する 2. データをビンに仕分ける 3. 仕分け完了=ソート完了なので出力 データは0から8までの範囲であると いうことが事前にわかっている場合 0から8までのビンを用意する 0 1 2 3 4 5 6 7 8 ビン 7 3 6 0 8 3 2 public final class BinSort { public static void sort(int[] anyTargetIntegers, int aMin, int aMax) { if(null == anyTargetIntegers){ throw new NullPointerException(); } BinSort.print(anyTargetIntegers); int[] bin = new int[aMax - aMin + 1]; for(int i = 0; i < bin.length; i ++){ bin[i] = 0; } int[] original = (int [])anyTargetIntegers.clone(); for(int i = 0; i < original.length; i++){ bin[original[i] - aMin]++; } int[] original = new int[anyTargetIntegers.length]; for(int i = 1; i < bin.length; i ++){ for(int i = 0; i < anyTargetIntegers.length; i++){ bin[i] += bin[i-1]; original[i] = anyTargetIntegers[i]; } } } } for(int i = original.length-1; i >= 0; i--){ int j = --bin[original[i] - aMin]; anyTargetIntegers[j] = original[i]; } BinSort.print(anyTargetIntegers); public static void print(int[] anyTargetIntegers) { int limit = anyTargetIntegers.length - 1; for(int count = 0; count < limit; count++){ if(10 > anyTargetIntegers[count]){ System.out.print(" "); } System.out.print(anyTargetIntegers[count] + ", "); } System.out.println(anyTargetIntegers[limit]); } [sakai@star 11]$ java BinSortTest 47, 18, 8, 7, 2, 4, 9, 0, 72, 88, 2, 5, 9, 10 0, 2, 2, 4, 5, 7, 8, 9, 9, 10, 18, 47, 72, 88 [sakai@star 11]$ ビンに仕分けて、取り出すだけ。 時間計算量は良い。 空間計算量は良くない。 ハッシュと探索 ソート 比較だけを使用 バブルソート クイックソート マージソート 比較以外の方法を使用 ビンソート 探索 比較だけを使用 線形探索 二分探索 あらかじめソートが必要 比較以外の方法を使用 ハッシュ法
© Copyright 2024 ExpyDoc