MIT Open course: Introduction to Algorithmsのまとめ(4~6回)
勉強の続き。
第四回
◯クイックソート
・ある数(ピボット)をソートされた位置に順番に移動させる方法
・入力に依存しないように、変形版としてランダムクイックソートがある(ピボットをランダムに選択)
・分析(証明)
計算時間,E[T(n)]=nlogn
第五回
◯ソートアルゴリズム速度まとめ
・クイックソート O(nlogn)
・ヒープソート O(nlogn)
・マージソート O(nlogn)
・Insertion Sort O(n^2)
◯比較ソートモデル(Comparison Sorting model)
・数列の順番を決定するのに比較のみを用いるモデル
・上の4つはいずれもこのモデルに属する
・決定木で書ける(ノードは比較式、葉は答え)
・nが大きくなると、木は巨大になるので書けない。(全並び替えが木ある必要がある)
・このモデルのもとでは、最速でもnlogn!!!←(葉の数)>=n!, (葉の数)<=2^h, worst case計算時間はh(木の高さ)
◯Counting sort
・全要素を含むバッファを別に用意しといて、各要素が何回ずつ出現したかを数える
・線形計算時間
◯Radix sort
・小さい桁から順番にcounting sortしていく
・線形計算時間
・要素が限定されているときに有効(ビット列とか)
第六回
◯Order Statistics n
・この配列からk番目に小さい要素を見つける
・naive→ソートしてk番目 O(nlogn)
◯Rand-select
・クイックソートのようにピボットを選ぶが、kが含まれるであろう側のグループのみしか考えない O(n)
・unlucky case、例えばピボットを選んで1とn-2にわかれた場合、T(n)=T(n-1)+Θ(n)でO(n^2)→どうにかならないか?
◯no-name Rand-select
・ピボットを工夫して選択(二つのサイズがともに1/4以上になるように)
1.5個の要素をもつ[n/5]個のグループにわけ、グループごとにmedianを見つける
2.medianのmedianを見つける
3.それをpivotにしてrand-select
・必見!ピボットの選択方法が神がかっている。なぜ5個か
QuickSort.java
public class QuickSort extends Sort{ public int[] sort(int[] A) { sort(A,0,A.length - 1); return A; } public void sort(int[] A,int p, int q) { if( p < q) { int r = partition(A,p,q); sort(A,p,r-1); sort(A,r + 1,q); } } public int partition(int[] A, int p, int q){ int i=p; int pivot = A[p]; for(int k = p+1;k<= q;k++){ if(A[k] < pivot) { int temp = A[i+1]; A[i+1] = A[k]; A[k] = temp; i++; } } int temp = A[i]; http://d.hatena.ne.jp/J0__0K/port A[i] = A[p]; A[p] = temp; return i; } public int[] combine(int[] subA, int[] subB){ int m = subA.length; int n = subB.length; int[] array = new int[m + n]; System.arraycopy(subA, 0, array, 0, m); System.arraycopy(subB, 0, array, m, n); return array; } }
CountingSort.java
import java.util.Arrays; public class CountingSort extends Sort{ public int[] sort(int[] A) { int n = A.length; int min = Integer.MAX_VALUE; int max = Integer.MIN_VALUE; for(int i = 0;i< n;i++){ min = Math.min(min, A[i]); max = Math.max(max, A[i]); } int nn = max - min + 1; int[] B = new int[n]; int[] C = new int[nn]; Arrays.fill(C, 0); for(int i = 0;i< n;i++) C[A[i]-min]++; for(int i = 1;i< nn;i++) C[i]+=C[i-1]; for(int i = n-1;i>=0;i--) B[--C[A[i]-min]] = A[i]; return B; } }
QuickSelect.java
public class QuickSelect { public int select(int[] A, int idx) { return select(A,0,A.length - 1,idx); } public int select(int[] A,int p, int q, int idx) { int r = partition(A,p,q); if( r == p + idx - 1 ) return A[r]; else if(r > p + idx- 1) return select(A,p,r-1,idx); else return select(A,r+1,q,idx-(r-p)-1); } public int partition(int[] A, int p, int q){ int i=p; int pivot = A[p]; for(int k = p+1;k<= q;k++){ if(A[k] < pivot) { int temp = A[i+1]; A[i+1] = A[k]; A[k] = temp; i++; } } int temp = A[i]; A[i] = A[p]; A[p] = temp; return i; } }