我已按照quickSelect了解并实施了quickSelect算法。我不确定的一件事是:为什么他们会k-pivot
和pivot-first+1
。
虽然我的实现与此链接完全相似,但它无效。
#include <stdio.h>
#include <string.h>
#define DEBUG 1
#define debug(fmt, ...)\
do{\
if(DEBUG)\
fprintf(stdout, "%s(%d) : " fmt "\n", __FUNCTION__, __LINE__, __VA_ARGS__);\
}while(0)
#define swap(a, b)\
do{\
if(a != b) {\
a = a ^ b;\
b = a ^ b;\
a = a ^ b;\
}\
}while(0)
int
partition(int *a, int low, int high)
{
int i = low, j = high;
int pivot = a[i];
i++;
while(i < j)
{
while(pivot >= a[i])
i++;
while(pivot < a[j])
j--;
if(i < j)
swap(a[i], a[j]);
}
swap(a[low], a[j]);
return j;
}
int
quick_select(int *a, int start, int end, int k)
{
if(start < end)
{
int pivot = partition(a, start, end);
if(k < (pivot - start + 1))
return quick_select(a, start, pivot, k);
else if( k > (pivot - start + 1))
return quick_select(a, pivot+1, end, k - pivot);
else
return a[pivot];
}
}
int
main()
{
int a[100], k, n;
int ret, i;
while(1)
{
printf("# of items : ");
scanf("%d", &n);
printf("Items : ");
for(i = 0; i<n; i++)
scanf("%d", &a[i]);
printf("<k> : ");
scanf("%d", &k);
ret = quick_select(a, 0, n-1, k);
printf("[%d] smallest element = [%d]\n", k, ret);
}
return 0;
}
输出:
./a.out
# of items : 10
Items : 1 2 3 4 5 6 7 8 9 10
<k> : 9
[9] smallest element = [32767]
答案 0 :(得分:2)
首先,noman是对的。第二个quick_select是
quick_select(a, pivot+1, end, k - (pivot-start+1));
其次,要注意输入的含义。 start
和end
在与当前递归调用相对应的原始列表中是绝对位置。 k
是当前列表[start, end]
pivot-start+1
是从pivot
开始的当前子列表中索引start
的相对位置。k - (pivot-start+1)
(在您的alg k - pivot
中)是以pivot开头的列表中k个最小元素的相对位置。例如,6 [1, 2, 3, 4, 5, 6]
列表中的第4个最小元素是从3开始的子列表中的第2个最小元素[3, 4, 5, 6]
答案 1 :(得分:0)
只是你没有在一个案例中做pivot-1而你没有从K中减去正确的值来找到下一个K.
假设你有8个数字,你得到的数据为5.这意味着什么?这意味着如果您按非递减顺序排序并且小于第5个索引的所有数字小于该值,则第5个索引处的数字是5个最小元素。因此,如果您正在寻找7个最小的数字(我们称之为K),您应该在哪里搜索?你应该搜索6到8对吗?但是如果您仍然搜索6到8范围内的7个最小数字,那么K号应该会发生什么?没有权利?
你认为你不应该从7中减去6(0到5)个数字吗?如果你仍然认为不?然后阅读,否则停止阅读。
假设你有5个弟弟,你是所有兄弟中最高的。一个盲人来到你家,想要知道谁是你们所有人中第五高的。所以你告诉他说两个名字,你会告诉他谁是这些兄弟中最高的。这是他唯一可以要求找到第五高的问题。所以他所做的是与quicksort类似的东西。如果他选择你的第三个兄弟作为支点,并安排你的兄弟,他们的身高小于左边三分之一,右边另一个。在此之后,如果他计算你的第三个兄弟站在哪里,他就会知道你的第三个兄弟是第三高的在你的房子。现在他应该在哪里寻找第五高,显然是在右边?不是吗?
但他不知道第四高的位置在哪里。对?他所知道的是,第四和第五高是向右。所以你有两个人站在右边,他们两个人的身高都超过了第3,盲人想要知道第5个最高,但在这两个人之间,你应该找到第4个最高或第2个最高(5-3)在正确的组中(范围是4到5)?
我相信你现在已经理解了。
quick_select(int *a, int start, int end, int k)
{
if(start < end)
{
int pivot = partition(a, start, end);
if(k < (pivot - start + 1))
return quick_select(a, start, pivot-1, k);
else if( k > (pivot - start + 1))
return quick_select(a, pivot+1, end, k - (pivot-start+1));
else
return a[pivot];
}
}