zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    著名的二分查找的BUG
    C/C++ static用法
    浅谈C++虚函数
    git备忘(长久更新)
    【经典问题】最大子串和
    水波纹效果
    博客迁址 xpeng.scorpionstudio.com
    终于,我们的新产品Fotor Slideshow Maker上线了!!
    分享一款浏览器扩展--美图搜索-图片搜索工具
    分享网页微信防撤回插件
  • 原文地址:https://www.cnblogs.com/lp3318/p/5678670.html
Copyright © 2011-2022 走看看