快排扩展——第k小的数

使用快排中的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;
}

posted @ 2012-05-04 19:17  KingsLanding  阅读(279)  评论(0编辑  收藏  举报