Quick-Select 1亿个数高速求第K小的数 分治法

Quick-Select 1亿个数快速求第K小的数 分治法

Quick-Select  1亿个数快速求第K小的数  分治法


利用快速排序的思想,一开始选取中枢元,然后左右调整,接着比对中枢元p和K的大小,如果 p+1 = k (数组从0开始), 那么a[p] 就是答案,因为在p之前的,肯定都是小于a[p]的, 在p之后的,肯定大于p, 所以 a[p] 就是第 p+1 小。假如 p+1 不等于K, 那么根据大小,进行左右调整。调整过程中,理想状态下,每次都砍掉一半,数组的起始坐标要进行调整。


代码:


// 快速排序法的修改

#include <iostream>
#include <ctime>
#include <cstdlib>
#include <algorithm>
#include <cstdio>

using namespace std;

const int MAX = 100000000;   // 1亿个数
int a[MAX];

// arr数组, n 数组个数, k 第几小
int findKMin(int arr[], int n, int k)
{
    if ( n<0 || n>MAX || k<=0 || k>n)
        return -1;

    // 假设以arr[0]为交换的中枢值, 进行左右交换
    int value = arr[0];
    int low = 0;
    int high = n-1;
    while(low < high)
    {
        while(low < high && arr[high] >= value)
            high--;
        arr[low] = arr[high];

        while(low < high && arr[low] <= value)
            low++;
        arr[high] = arr[low];
    }
    arr[low] = value;

    // 对 K 进行判断,  左右搜寻的时候,要变更arr的起始位置
    if (low+1 == k)
        return arr[low];
    else if (low+1 < k)   // 在右边继续搜寻
        return findKMin(arr+low+1, n-low-1, k-low-1);
    else    // low > k  // 在左边搜寻
        return findKMin(arr, low+1, k);
}

int main(void)
{
    // 产生随机数
    srand( (unsigned)time(NULL) );
    for(int i=0; i<MAX; ++i)
    {
        a[i] = (rand()+1)*(rand()+1) ;
        //printf("%d ", a[i]);
    }

    int k = 5;

    //int num = findKMin(a, MAX, k);   // start at 0
    //printf("%d\n", num);


    // 普通排序搜索
    sort(a, a+MAX);
    printf("%d", a[k-1]);

    /*
    for(int i=0; i<k; ++i)
    {
        printf("%d ", a[i]);
    }
    printf("\n");
    */

    return 0;
}



时间的比对:

数据比较大,产生1亿个随机数的大概时间。

Quick-Select  1亿个数高速求第K小的数  分治法


用分治法求解的时间。

Quick-Select  1亿个数高速求第K小的数  分治法


普通排序之后定位的时间, 数据随机产生,所以与分治法求解的结果不同。

Quick-Select  1亿个数高速求第K小的数  分治法



明显看出两者的时间相差是非常大的,


版权声明:本文为博主原创文章,未经博主允许不得转载。 http://blog.****.net/core__code