Я осуществил следующий Быстрый выбор алгоритма для достижения O(n)
сложности для срединного выбора (в более общем случае КТН наименьшее число):КТН наименьшее число - быстрая сортировка быстрее Быстрый выбор
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);
с результатами аналогичных qsort took 0.280432
, qselect took 8.516676
для массива 10000 элементов. Почему quicksort быстрее, чем quickselect?
Что о 100k элементов? 1M? –
Почему вы 'qsort'ing' points_ptr' каждый раз? – IVlad
O() указывает, как использование ресурсов * масштабируется *, а не сколько ресурсов (например, времени) оно * использует *. Алгоритм, который масштабируется лучше, все равно может занять больше времени, давая данный ввод. – ikegami