アルゴリズムとデータ構造 2012年6月27日 酒居敬一([email protected]) http://www.info.kochi-tech.ac.jp/k1sakai/Lecture/ALG/2013/index.html 整列(ソート) • 配列を使用するソートアルゴリズム – 挿入法 – 時間計算量 O(n 2 ) – バブルソート – 時間計算量 – シェルソート – 時間計算量 O(n 2 ) O(n 2 ) – クイックソート – 時間計算量 O ( n log n) – 時間計算量は最悪でも O ( n 2 ) • 空間計算量はいずれも O (n) 2 テストデータとテスト用メソッド private final static String[] test_data_string = { "東京", "北海道", "高知", "兵庫", "鹿児島", "沖縄", "青森", }; private final static Integer[] test_data_int = { 47, 18, 8, 7, 2, 4, 9, 0, 72, 88, 2, 5, 9, 10, }; public static void main(String[] args) { int n; StringBuffer sb = new StringBuffer(); String[] data1 = test_data_string.clone(); n = sort(data1); for (String e : data1) { sb.append(e).append(", "); } sb.append("\ncompareTo()を呼んだ回数 ").append(n).append('\n'); Integer[] data2 = test_data_int.clone(); n = sort(data2); for (Integer e : data2) { sb.append(e).append(", "); } sb.append("\ncompareTo()を呼んだ回数 ").append(n).append('\n'); System.out.print(sb.toString()); } 3 public class SimpleSort { public static <E extends Comparable<E>> int sort(E[] array) { int n = 0; for(int i = 0; i < (array.length - 1); i++){ 単純な整列アルゴリズム for(int j = i+1; j < array.length; j++){ (147ページ) n++; if(array[j].compareTo(array[i]) < 0){ E tmp = array[j]; array[j] = array[i]; array[i] = tmp; } } } return n; } } 兵庫, 北海道, 東京, 沖縄, 青森, 高知, 鹿児島, compareTo()を呼んだ回数 21 0, 2, 2, 4, 5, 7, 8, 9, 9, 10, 18, 47, 72, 88, compareTo()を呼んだ回数 91 4 public class SelectionSort { public static <E extends Comparable<E>> int sort(E[] array) { int n = 0; for(int i = 0; i < (array.length - 1); i++){ int minpos = i; for(int j = i+1; j < array.length; j++){ n++; if(array[j].compareTo(array[minpos]) < 0){ minpos = j; } } E tmp = array[minpos]; array[minpos] = array[i]; array[i] = tmp; } return n; } } 選択法 (149ページ) 兵庫, 北海道, 東京, 沖縄, 青森, 高知, 鹿児島, compareTo()を呼んだ回数 21 0, 2, 2, 4, 5, 7, 8, 9, 9, 10, 18, 47, 72, 88, compareTo()を呼んだ回数 91 5 バブルソート (149ページ) 10 8 10 8 10 15 10 3 15 15 5 15 32 15 5 15 32 3215 12 32 12 1 32 24 6 24 > >38 10 < < > > < < > > > >16 > < 10 38 10 83 10 53 10 15 5 15 12 5 15 32 12 1 15 12 32 61 15 32 61 32 24 6 32 24 整列済み 入れ替え 入れ替えない 入れ替え 入れ替えない 入れ替え 入れ替えない 入れ替え 入れ替えない 入れ替え 入れ替え 入れ替え 入れ替えない 入れ替え 入れ替え 残りも同様に整列させると… 1 3 5 6 8 10 12 15 24 32 6 public class BubbleSort { public static <E extends Comparable<E>> int sort(E[] array) { int n = 0; boolean isChanged = false; int limit = array.length - 1; while (true) { isChanged = false; for (int count = 0; count < limit; count++) { if (array[count].compareTo(array[count + 1]) > 0) { E temp = array[count]; array[count] = array[count + 1]; array[count + 1] = temp; isChanged = true; } n++; } limit--; if (!isChanged) break; } return n; } 兵庫, 北海道, 東京, 沖縄, } 青森, 高知, 鹿児島, compareTo()を呼んだ回数 18 0, 2, 2, 4, 5, 7, 8, 9, 9, 10, 18, 47, 72, 88, compareTo()を呼んだ回数 81 7 挿入法 (150ページ) 10 8 3 1 10 8 10 5 3 3 10 8 5 15 8 10 6 15 12 5 32 8 10 15 32 12 15 32 12 15 1 24 32 6 32 24 以上で整列おわり!… 1 3 5 6 8 10 12 15 24 32 8 public class InsertionSort { public static <E extends Comparable<E>> int sort(E[] array) { int n = 0; for(int i = 1; i < array.length; i++){ E w = array[i]; int j = i - 1; while((j >= 0) && w.compareTo(array[j]) < 0){ array[j+1] = array[j]; j--; n++; } n++; array[j+1] = w; } return n; } } 兵庫, 北海道, 東京, 沖縄, 青森, 高知, 鹿児島, compareTo()を呼んだ回数 14 0, 2, 2, 4, 5, 7, 8, 9, 9, 10, 18, 47, 72, 88, compareTo()を呼んだ回数 59 9 シェルソート (156ページ) h 14 10 5 3 1 8 5 3 3 8 5 15 8 6 1 10 5 24 6 8 32 10 12 24 15 24 12 15 1 24 10 6 32 24 以上で整列おわり!… 1 3 5 6 8 10 12 15 24 32 10 public class ShellSort { public static <E extends Comparable<E>> int sort(E[] array) { int n = 0; int h; for(h = 1; h < array.length; h = h*3 + 1); // nより小さい範囲で最大のhを求める while(h > 1){ h /= 3; for(int i = h; i < array.length; i++){ E w = array[i]; int j = i - h; n++; while((j >= 0) && w.compareTo(array[j]) < 0){ array[j+h] = array[j]; j -= h; n++; } array[j+h] = w; } } return n; 兵庫, 北海道, 東京, 沖縄, 青森, 高知, 鹿児島, } } compareTo()を呼んだ回数 17 0, 2, 2, 4, 5, 7, 8, 9, 9, 10, 18, 47, 72, 88, compareTo()を呼んだ回数 53 11 シェルソートの計算量 • を 1, 3, 7, 15, ..., 2 1 32 とすると最悪時間計算量が O( n ) になる。 • をうまく選ぶと 最悪時間計算量 O( n 4 3 ) になる。 • を 1, 4, 13, 40, 121, ..., 3hk 1 1 1.25 とすると平均時間計算量が O(n ) になる。 h k h h 12 ソートの計算量 n個のデータの並びは n! とおり存在する ソートとは、n! の並びのどれであるかを特定すること 1回の比較で並びの可能性が1/2にできる 並びの可能性が1以下にできればソート完了 そのときの比較回数をkとすれば、 すなわち Stirlingの公式から およそ n log nという計算量になる 比較を使う限りの性能上限 13 線形なデータ構造における整列 (ソート) • 比較によるもの – バブルソート – クイックソート – マージソート • 比較によらないもの – ビンソート 14 計算量を減らす • 比較を用いたソーティングアルゴリズム – 大小といった情報は、比較することで得られる – データの並びについては仮定をおかない – そうするとO(n log2 n)は下回れない • 比較を用いないソーティング – 情報を得なければいけない点は変わらない – データの性質に合ったアルゴリズムを使う バブルソートばかりを使うのはやめて、クイックソートの ような性能の良いアルゴリズムを使いましょうという話は 間違ってはいない。 ただし、 データの性質をも考慮に入れてそれが最善か を考える必要はある。 15 アルゴリズムとデータ構造 シェルソート解答例 元のデータ 10 8 3 15 5 32 12 1 6 24 [0]-[4]-[8]をソート 5 8 3 15 6 32 12 1 10 24 [1]-[5]-[9]をソート 5 8 3 15 6 24 12 1 10 32 [2]-[6]をソート 5 8 3 1 6 24 12 15 10 32 [3]-[7]をソート 5 8 3 1 6 24 12 15 10 32 h 1 [2]を[0]へ挿入 3 5 8 1 6 24 12 15 10 32 挿入法でソート [3]を[0]へ挿入 1 3 5 8 6 24 12 15 10 32 [4]を[3]へ挿入 1 3 5 6 8 24 12 15 10 32 [6]を[5]へ挿入 1 3 5 6 8 12 24 15 10 32 [7]を[6]へ挿入 1 3 5 6 8 12 15 24 10 32 1 3 5 6 8 10 12 15 24 32 h4 [9]を[5]へ挿入 ソート完了 アルゴリズムとデータ構造 演習 学生番号: 名前: 問題: 元のデータがシェルソートにより、h=7, 3, 1 で順にソートされてゆくとき、その途中経過を 書きなさい。hの値と場所を示すこと。色を塗ったり、影をつけたりする必要はない。 10 8 3 15 5 32 12 1 6 24
© Copyright 2024 ExpyDoc