我有以下分区方法和kthsmallest方法(快速排序的变化),它适用于某些情况,但在少数情况下给出了值32767。
void swap(int* a, int* b){
int temp = *b;
*b = *a;
*a = temp;
}
int partition(int* arr, int l, int r){
int pivot = arr[r];
int i = l, j=0;
for(j=l; j<=r-1; j++){
if(arr[j] <= pivot){
swap(&arr[i], &arr[j]);
i++;
}
}
swap(&arr[i], &arr[j]);
return i;
}
kthsmallest函数如下: -
int kthsmallest(int* arr, int low, int high, int k){
/* low = 0 and high = #elements - 1 */
/* k is in between 1 to high + 1 */
if (k>0 & k<=high-low+1) {
// pos is partitioning index, arr[p] is now at right place
int pos = partition(arr, low, high);
// Separately sort elements before / partition and after partition
if(pos-low == k-1){
return arr[pos];
}
//if position returned is greater than k, recurse left subarray
else if(pos-low > k-1){
return kthsmallest(arr, low, pos-1, k);
}
return kthsmallest(arr, pos+1, high, k-(pos+1));
}
}
然而,当我在kthsmallest函数中更改最后一个调用时,它可以工作,即
更改:return kthsmallest(arr, pos+1, high, k-(pos+1));
收件人:return kthsmallest(arr, pos+1, high, k-(pos+1)+low);
我想了解为什么我需要将低值添加到k-(pos + 1)。因为在我看来,当我们在递归进入的右边有子阵列时,大数组中的第k个最小数字归结为k - 最后一个分区元素-1,即k-(pos + 1)。
答案 0 :(得分:2)
当你有没有理由使函数递归开始时,你遇到的一个问题就是试图将一个quickselect例程塞进一个递归函数中。您需要做的就是确定'k'
元素所在的分区,不需要排序。您kthsmallest
所需要的只是:
/** select the ZERO BASED 'k' element from 'arr'.
* where 'low' and 'high' are the ZERO BASED low
* and high indexes for 'arr'.
*/
int kthsmallest (int *arr, int low, int high, int k)
{
for (;;) {
if (low == high)
return arr[low];
int pos = partition (arr, low, high);
if (k == pos)
return arr[k];
else if (k < pos)
high = pos - 1;
else
low = pos + 1;
}
}
使用精确的partition
和swap
函数,您可以编写一个小示例程序来测试数组中每个元素的k
。 ( 注意: 返回的元素基于 零索引k ,例如首先最小元素从数组末尾偏移零 - 就像在C的其余部分一样
#include <stdio.h>
void swap (int *a, int *b);
int partition (int *arr, int l, int r);
/** select the ZERO BASED 'k' element from 'arr'.
* where 'low' and 'high' are the ZERO BASED low
* and high indexes for 'arr'.
*/
int kthsmallest (int *arr, int low, int high, int k)
{
for (;;) {
if (low == high)
return arr[low];
int pos = partition (arr, low, high);
if (k == pos)
return arr[k];
else if (k < pos)
high = pos - 1;
else
low = pos + 1;
}
}
int main (void) {
int a[] = { 51, 86, 34, 79, 92, 68, 14, 47, 22, 6 },
nelem = sizeof a / sizeof *a;
for (int i = 0; i < nelem; i++)
printf (" nth (%2d) element is : %d\n", i,
kthsmallest (a, 0, nelem - 1, i));
return 0;
}
void swap (int *a, int *b)
{
int temp = *b;
*b = *a;
*a = temp;
}
int partition (int *arr, int l, int r)
{
int pivot = arr[r];
int i = l, j = 0;
for (j = l; j <= r - 1; j++) {
if (arr[j] <= pivot) {
swap (&arr[i], &arr[j]);
i++;
}
}
swap (&arr[i], &arr[j]);
return i;
}
示例使用/输出
$ ./bin/kthsmall
nth ( 0) element is : 6
nth ( 1) element is : 14
nth ( 2) element is : 22
nth ( 3) element is : 34
nth ( 4) element is : 47
nth ( 5) element is : 51
nth ( 6) element is : 68
nth ( 7) element is : 79
nth ( 8) element is : 86
nth ( 9) element is : 92