BFPRT算法求无序数组中第k个值

很好的总结在这:

http://blog.csdn.net/acdreamers/article/details/44656295

 

BFPRT的两个过程:

I.将数组进行分组,并对每个组进行插入排序,最后得到整体的中位数。时间复杂度为O(n);

II.根据上一步的到的中位数,进行递归划分

  1 // BFPRT.cpp : 定义控制台应用程序的入口点。
  2 //主要过程I.得到中位数的中位数 II.根据中位数进行划分
  3 //
  4 
  5 #include "stdafx.h"
  6 #include <iostream>
  7 
  8 using namespace std;
  9 
 10 void InsertSort(int*a,int left,int right)
 11 {
 12     for(int i = left + 1; i != right + 1; i++)
 13     {
 14         for(int j = i;j != left;j--)
 15         {
 16             if(a[j-1] > a[j])
 17                 swap(a[j-1],a[j]);
 18             else
 19                 break;
 20         }
 21     }
 22 }
 23 
 24 int FindMid(int *a,int left,int right)
 25 {
 26     if(left == right)
 27         return a[left];
 28     int i = 0;
 29     int n = 0;
 30     for(i = left;i < right-5;i += 5)
 31     {
 32         InsertSort(a,i,i+4);
 33         n = i - 1;// 得到n,n/5即为当前处理的组数
 34         swap(a[left + n / 5],a[i + 2]);
 35         //排序后,a[i+2]都为各组的中位数。将中位数依次交换到前边
 36     }
 37 
 38     //处理剩余的数据,假设14个数,i = 10时,不满足i<r-5没有进入循环体,
 39     int num = right - i + 1;//最后一个分组的长度
 40     if(num > 0)
 41     {
 42         InsertSort(a,i,i+num-1);
 43         n = i - 1;
 44         swap(a[left+n/5],a[i+num/2]);
 45         //a[i+num/2]中i为剩余数组开头,长度为num,中位数偏移为num/2
 46     }
 47     n /= 5;//上一次所得中位数组数;如14个数,第一次寻找得到3个中位数,分别
 48     //被交换到了数组开始的位置。n = i - 1 (=9);n /= 5;(n = 9/5 == 1),
 49     //即只得到一组中位数
 50     
 51     if(n == left)
 52         return a[left];
 53     else 
 54         return FindMid(a,left,left+n); 
 55 }
 56 
 57 int FindId(int*a,int left,int right,int midNum)
 58 {
 59     for(int i = left;i <= right;i++)
 60         if(a[i] == midNum)
 61             return i; 
 62     return -1;
 63 }
 64 
 65 
 66 //划分过程
 67 int myPartition(int *a,int left,int right,int med_index)
 68 {
 69     swap(a[right],a[med_index]);
 70     int pivot = a[right];
 71 
 72     while(left < right)
 73     {
 74         while(left < right && a[left] < pivot)
 75             ++left;
 76         if(left < right)
 77             swap(a[left],a[right]);
 78         while(left < right && a[right] >= pivot)
 79             --right;
 80         if(left < right)
 81             swap(a[left],a[right]);
 82     }
 83     return left;
 84 }
 85 
 86 int bfprt(int *a,int left,int right,int k)
 87 {
 88     int midNum = FindMid(a,left,right);//找中位数的中位数
 89     int id = FindId(a,left,right,midNum);//得到中位数对应的下标
 90     int index = myPartition(a,left,right,id);//划分
 91 
 92     int m = index - left + 1;//划分所得结果是数组中第几个数
 93     
 94     if(m == k)return a[index];
 95     else if (m > k)
 96         return bfprt(a,left,index-1,k);
 97     else
 98         return bfprt(a,index+1,right,k-m);
 99     return 0;
100 }
101 
102 
103 int _tmain(int argc, _TCHAR* argv[])
104 {
105     int n;
106     cout<<"请输入n:"<<endl;
107     cin>>n;
108     int *a = new int[n];
109     cout<<"请输入"<<n<<"数组成数组:"<<endl;
110     for(int i = 0; i < n;i++)
111         cin>>a[i];
112 
113     int k;
114     cout<<"请输入k:"<<endl;
115     cin>>k;
116 
117     cout<<""<<k<<"个数为:"<<bfprt(a,0,n-1,k)<<endl;
118     system("pause");
119     return 0;
120 }
BFPRT

 

posted @ 2016-07-17 15:42  lp3318  阅读(189)  评论(0编辑  收藏  举报