/**
* BFPTR算法(前K小数问题)
*
* author 刘毅(Limer)
* date 2017/01/25
* language C++
*/
#include<iostream>
#include<algorithm>
using namespace std;
/* 对arry[left]...arry[right]进行插入排序(升序) */
void InsertSort(int arry[], int left, int right)
{
for (int i = left + 1; i <= right; i++)
{
int j = i;
while (j - 1 >= left&&arry[j] < arry[j - 1]) //j - 1 >= left避免数组越界
{
swap(arry[j - 1], arry[j]);
j--;
}
}
}
/* 找到中位数的中位数,返回其下标 */
int FindMidMid(int arry[], int left, int right)
{
if (right - left + 1 <= 5) //如果不足5个
{
InsertSort(arry, left, right);
return (left + right) >> 1;
}
int j = left - 1;
for (int i = left; i <= right; i += 5) //5个一组插入排序取中位数,并统一放在左侧
{
InsertSort(arry, i, i + 4);
swap(arry[++j], arry[i + 2]);
}
return FindMidMid(arry, left, j); //直至仅出现一个的中位数
}
/* 划分,pivot为划分基准的下标 */
int Partion(int arry[], int left, int right, int pivot_index)
{
swap(arry[pivot_index], arry[right]); //把基准放置右侧末尾
int j = left;
for (int i = left; i < right; i++) //比基准小的都放在左侧
{
if (arry[i] <= arry[right])
swap(arry[j++], arry[i]);
}
swap(arry[j], arry[right]); //最后把基准换回来
return j;
}
void BFPRT(int arry[], int left, int right, int k)
{
if (left == right)
return;
int pivot_index = FindMidMid(arry, left, right); //找到中位数的中位数的下标,其值作为基准
int index = Partion(arry, left, right, pivot_index); //以基准划分
int num = index - left + 1;
if (num == k)
return;
else if (num > k)
BFPRT(arry, left, index - 1, k);
else
BFPRT(arry, index + 1, right, k - num);
}
int main()
{
int k = 1;
int arry[10] = { 1,1,2,3,1,5,-1,7,8,-10 };
BFPRT(arry, 0, 9, k);
for (int i = 0; i < 10; i++)
cout << arry[i] << " ";
cout << endl;
return 0;
}
如果把5换成3带进去算,最后出来的10c/3这个整体都会变小,也就是复杂度比5的小啊,那为什么不用3呢,维基上的我也看了,但是按照我这个思路就是不对,或者我的这个解法存在问题,望指正。