/* p番目の要素を選択する平均時間O(n)の確率アルゴリズム、 LAZYSELECTのプログラム例 */ #include #include #include #define N 10000 /* 配列Aの最大サイズ */ #define SEED 13 /* 乱数の種 */ /* 関数の宣言 */ int lazyselect(int i, int j, int p, int *A); int rand_from(int min, int max); void quicksort(int i, int j, int *A); /* 第1回参照 */ int partition(int i, int j, int a, int *A); /* 第1回参照 */ int pivot(int i, int j, int *A); /* 第1回参照 */ void swap(int i, int j, int *A); /* 第1回参照 */ main() /* 第p要素の選択のテストプログラム -- LAZYSELECT -- */ { int A[N], n, i, p, ap; FILE *file; file=fopen("selectdata", "r"); /* データファイルの読込 */ fscanf(file, "%d", &n); fscanf(file, "%d", &p); if(n>N) /* 配列サイズのチェック */ { printf("Illegal array size n = %d for N = %d\n", n, N); exit(1); } for(i=0; inB) h=nB; L=lazyselect(i, i+nB-1, l, A); /* Bの大きさl番目の要素 */ H=lazyselect(i, i+nB-1, h, A); /* Bの大きさh番目の要素 */ kH=partition(i, j, H, A); /* A1とA2の分割 */ if(kHi+p-1) /* p番目はA11にある */ return(lazyselect(i, kL-1, p, A)); else /* p番目はA12にある */ return(lazyselect(kL, kH-1, p-kL+i, A)); } } } int rand_from(int min, int max) /* 区間[min, max]からランダムに整数を選ぶ */ /* randは0からRAND_MAXまでの乱整数を生成する標準関数 */ { return((int)(((double)rand()/((unsigned)RAND_MAX+1)) *(max-min+1))+min); } void quicksort(int i, int j, int *A) /* 配列A[i],...,A[j]をクイックソートにより整列 */ { int a, pv, k; pv=pivot(i, j, A); if(pv!=-1) /* 軸要素が見つかった場合 */ { a=A[pv]; /* 軸要素 */ k=partition(i, j, a, A); /* 軸要素A[pv]により分割 */ quicksort(i, k-1, A); /* 前半の整列 */ quicksort(k, j, A); /* 後半の整列 */ } return; } int partition(int i, int j, int a, int *A) /* A[i],...,A[j]を軸要素aによって分割 */ /* 前半はA[i],...,A[k-1]=aを満たす */ /* 上記のkを出力 */ { int l, r, k; l=i; r=j; /* lは左から、rは右から */ while(A[l]=a) r=r-1; while(l<=r) /* A[l]>=aとA[r]=a) r=r-1; /* つぎのlとrを計算 */ } k=l; return(k); } int pivot(int i, int j, int *A) /* A[i],...,A[j]から軸要素A[pv]を選びpvを出力 */ /* A[pv]はA[i]と最初に異なるA[k]の大きい方;すべて同じならpv=-1 */ { int pv, k, h, s0, s1, s2; s0=j-i; s1=(s0+1)/2; if(s0%2==0) s2=s1; else s2=s1-1; h=1; k=i+s1; /* s1とs2の交互のステップ幅でkを増加 */ while(A[i]==A[k] && hj) k=k-j+i-1; /* kがjを越える場合の修正 */ h=h+1; } if(A[i]>A[k]) pv=i; else if(A[i]