よりも私は(もっと一般的に最小の数をk番目)の中央値選択のためのO(n)
複雑性を達成するために、次のquickselectのアルゴリズムを実装している:は、k番目の最小の数 - クイックソートより速いquickselect
static size_t partition(struct point **points_ptr, size_t points_size, size_t pivot_idx)
{
const double pivot_value = points_ptr[pivot_idx]->distance;
/* Move pivot to the end. */
SWAP(points_ptr[pivot_idx], points_ptr[points_size - 1], struct point *);
/* Perform the element moving. */
size_t border_idx = 0;
for (size_t i = 0; i < points_size - 1; ++i) {
if (points_ptr[i]->distance < pivot_value) {
SWAP(points_ptr[border_idx], points_ptr[i], struct point *);
border_idx++;
}
}
/* Move pivot to act as a border element. */
SWAP(points_ptr[border_idx], points_ptr[points_size - 1], struct point *);
return border_idx;
}
static struct point * qselect(struct point **points_ptr, size_t points_size, size_t k)
{
const size_t pivot_idx = partition(points_ptr, points_size, rand() % points_size);
if (k == pivot_idx) { //k lies on the same place as a pivot
return points_ptr[pivot_idx];
} else if (k < pivot_idx) { //k lies on the left of the pivot
//points_ptr remains the same
points_size = pivot_idx;
//k remains the same
} else { //k lies on the right of the pivot
points_ptr += pivot_idx + 1;
points_size -= pivot_idx + 1;
k -= pivot_idx + 1;
}
return qselect(points_ptr, points_size, k);
}
その後、私はglibcののqsort()
と比較してみましたO(nlog(n))
となり、その優れた性能に驚いた。
double wtime;
wtime = 0.0;
for (size_t i = 0; i < 1000; ++i) {
qsort(points_ptr, points_size, sizeof (*points_ptr), compar_rand);
wtime -= omp_get_wtime();
qsort(points_ptr, points_size, sizeof (*points_ptr), compar_distance);
wtime += omp_get_wtime();
}
printf("qsort took %f\n", wtime);
wtime = 0.0;
for (size_t i = 0; i < 1000; ++i) {
qsort(points_ptr, points_size, sizeof (*points_ptr), compar_rand);
wtime -= omp_get_wtime();
qselect(points_ptr, points_size, points_size/2);
wtime += omp_get_wtime();
}
printf("qselect took %f\n", wtime);
10000個の素子のアレイのためのqsort took 0.280432
、qselect took 8.516676
と同様の結果を有する:ここで、測定コードです。クイックソートがquickselectより速いのはなぜですか?
どう100K程度の要素? 1M? –
毎回 'points_ptr'を' qsort'するのはなぜですか? – IVlad
O()は、リソース使用量*がどのくらいのリソース(時間など)ではなく*どのように使用されるかを示します*。より良いスケーリングを行うアルゴリズムは、与えられた入力を与えるのに時間がかかります。 – ikegami