算法思想见题库
代码如下:
void swap(int * a, int * b){
assert(a != NULL);
assert(b != NULL);
if(a != b){
*a ^= *b;
*b ^= *a;
*a ^= *b;
}
}
int partition(int a[], int left, int right){
assert(a != NULL);
int mid = left + (right-left)/2;
if(a[left] < a[mid]) swap(&a[left], &a[mid]);
if(a[left] < a[right]) swap(&a[left], &a[right]);
if(a[right] < a[mid]) swap(&a[right], &a[mid]);
int i, div = left;
for(i = left; i < right; i++){
if(a[i] > a[right]){
swap(&a[i], &a[div]);
div++;
}
}
swap(&a[div], &a[right]);
return div;
}
int get_kth(int a[], int n, int k){ //非递归形式
assert(a != NULL);
assert(n > 0);
assert(k > 0);
int left = 0, right = n-1;
int k_need = k; //k_need表示在当前区间内需要找第几大的数
int div = partition(a, left, right);
int k_get = div-left+1; //k_get表示在当前区间内找到了第几大的数
while(k_get != k_need){
if(k_get < k_need){
k_need -= k_get;
left = div+1;
}
else //当k_get > k_need时,不需要更新k_need
right = div-1;
div = partition(a, left, right);
k_get = div-left+1;
}
return div; //最后找到的第N大的数必然在div上,想想为什么
}
int new_get_kth(int a[], int left, int right, int k_need){ //递归形式,可读性更好
assert(a != NULL);
assert(k_need > 0);
int div = partition(a, left, right);
int k_get = div-left+1;
if(k_get < k_need) return new_get_kth(a, div+1, right, k_need-k_get);
else if(k_get > k_need) return new_get_kth(a, left, div-1, k_need);
else return div;
}