使用快排中的partition方法,可以很快找到一个无序序列中的第k小的数。
思想:对于一个数组a[0...n-1],分段成a[0...st-1],a[s],a[st+1...n-1]
分组后,a[0...st-1]里面的元素都小于等于a[st],a[st+1...n-1]里面的元素都大于等于a[st]. 所以,如果 st==k-1,那么a[st]就是要求的数。
如果 st>k-1,那么要求的数在a[0...st-1]里。 如果 st<k-1,那么要求的数在a[st+1...n-1]里。
因此我们把范围缩小到 a[0...st-1]或者a[st+1...n-1]里,然后对缩小范围后的数组也做同样的操作。
#include <iostream>
#include <algorithm>
#include <ctime>
#include <iterator>
using namespace std;
const int NUM = 20;
int partition(int a[],int left, int right)
{
int L = left;
int R = right;
while(left < right)
{
while(a[left] <= a[L] && left != R)
left++;
while(a[right] >= a[L] && right != L)
right--;
swap(a[left],a[right]);
}
swap(a[left],a[right]);
swap(a[L],a[right]);
return right;
}
int Search(int a[], int left, int right, int k)
{
int position = 0;
int local_left = left;
int local_right = right;
while(local_left <= local_right)//注意:这里需要有等号
{
position = partition(a, local_left, local_right);
if(position == k - 1)
return a[position];
else if( position < k - 1)
{
local_left = position + 1;
}
else
local_right = position - 1;
}
//cout << "position : "<<position<<endl;
//cout << "local_left: " << local_left << "\t" << "local_right: "<<local_right<<endl;
return -1;
}
void QuickSort(int a[],int left,int right)
{
int i;
if(left<right)
{
i=partition(a,left,right); //分割
QuickSort(a,left,i-1); //将两部分分别排序
QuickSort(a,i+1,right);
}
}
int main()
{
int a[NUM] = {0};
int k = 0;
srand(time(NULL));
for(int i = 0; i < NUM; i++)
a[i] = rand() % 100;
k = rand() % NUM;
//copy(a,a + NUM, ostream_iterator<int>(cout, " "));
cout<<endl;
cout <<k<<"th number is : "<<Search(a,0,NUM - 1, k) <<endl;
QuickSort(a,0,NUM - 1);
///下面主要是方便查看结果
copy(a,a + NUM / 2, ostream_iterator<int>(cout, " "));
cout << endl;
copy(a + NUM / 2,a + NUM , ostream_iterator<int>(cout, " "));
return 0;
}