快速排序求数组中第n大元素
还不了解快速排序的柚子,请参考我的这篇博客
//快速排序求数组中第n大的元素
// 寻找arr数组中第k小的元素, k从1开始索引, 即最小元素是第1小元素, 以此类推
template<typename T>
T findN(T arr[], int n, int key)
{
return __findN(arr, 0, n - 1, key - 1);
}
// 求出arr[l...r]范围里第k小的数
template<typename T>
T __findN(T arr[], int l , int r, int key)
{
if(l >= r) return arr[l];
// partition之后, arr[p]的正确位置就在索引p上
int p = __partition(arr, l, r);
if( p == key) // 如果 k == p, 直接返回arr[p]
{
return arr[p];
}
else if( p > key) // 如果 k < p, 只需要在arr[l...p-1]中找第k小元素即可
{
return __findN(arr, l, p - 1, key);
}
else
{
// 如果 k > p, 则需要在arr[p+1...r]中找第k-p-1小元素
// 注意: 由于我们传入__selection的依然是arr, 而不是arr[p+1...r],
// 所以传入的最后一个参数依然是k, 而不是k-p-1
return __findN(arr, p + 1, r, key);
}
}
//partition过程,与快速排序的partition过程一样
template<typename T>
int __partition(T arr[], int l, int r)
{
T v = arr[l];
int i = l + 1; // 保证了刚开始 arr[l +1 , i) 为空
int j = r;
while(1)
{
while(i <= r && arr[i] < v) i++;
while(j >= l + 1 && arr[j] > v) j--;
if(i > j) break;
swap(arr[i++], arr[j--]);
}
swap(arr[l], arr[j]);
return j;
}