借助刚才的划分算法,我们可以比较容易的求出第K大的数,平均性能为O(N),最坏可能是O(N^2)。
注意关于idx的选择,随机的话效果会比选left、right和median好,如果数据不是很特殊的化。
#include <stdio.h>
typedef int TYPE;
int cmp(TYPE a, TYPE b)
{
return a - b;
}
void swap(TYPE* a, TYPE* b)
{
TYPE tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
int partition(TYPE* arr, int left, int right, int pivotIndex)
{
//First swap arr[pivotIndexx] and arr[right]
TYPE pivot = arr[pivotIndex];
int store, i;
swap(&arr[pivotIndex], &arr[right]);
//Scan from left to right
store = i = left;
for(;i<right;i++)
{
if(cmp(arr[i], pivot)<=0)
{
swap(&arr[store], &arr[i]);
store++;
}
}
//Final swap arr[store] and arr[right](pivot)
swap(&arr[store], &arr[right]);
return store;
}
//Return the arr[k]
TYPE kth(TYPE* arr, int left, int right, int k)
{
//Select the midian and partition the array
int idx = (left + right) / 2;
int pivotIndex = partition(arr, left, right, idx);
if( left + k - 1 == pivotIndex)
{
return arr[pivotIndex];
}
if( left + k - 1 < pivotIndex)
{
return kth(arr, left, pivotIndex - 1, k);
}
if( left + k - 1 > pivotIndex)
{
return kth(arr, pivotIndex + 1, right, k - (pivotIndex - left +1));
}
}
int main()
{
TYPE arr[16] = {15, 9, 8, 1, 4, 11, 7, 12, 13, 6, 5, 3, 16, 2, 10, 14};
int len = sizeof(arr)/sizeof(TYPE);
int store;
int k;
//partition
//store = partition(arr, 0, len - 1, 9);
//printf("Pivot\t%d\n",store);
//kth
k = 15;
printf("%dth\t%d\n",k,kth(arr,0,len-1,k));
//print
//int i;
//for(i=0;i<len;i++)
//{
// printf("%d ",arr[i]);
//}
printf("\n");
}
拓展:
HDOJ
Kth number