topk问题C++实现

实现1:

#include 

using namespace std;

int partition(int a[], int left, int right)
{
    //从左、中、右3个元素中取中间值放在最右边
    int mid = (right - left)/2;
    if (a[left] > a[mid])
        swap(a[left], a[mid]);
    if (a[right] < a[left])
        swap(a[right], a[left]);
    if (a[right] > a[mid])
        swap(a[right], a[mid]);

    int i = left - 1;
    for(int j = left; j < right; j++)
        if (a[j] <= a[right])
            swap(a[++i], a[j]);

    swap(a[++i], a[right]);
    return i;
}

int topk(int a[], int left, int right, int k)
{
    if (left == right)
        return a[left];

    int mid = partition(a, left, right);
    int cur = mid - left + 1;

    if (cur == k)
        return a[k - 1];
    else if (k < cur)
        return topk(a, left, mid - 1, k);
    else
        return topk(a, mid+1, right, k-cur);
}

int main()
{
    int a[] = {1,2,3,4,5,6,7};

    cout << topk(a, 0, 6, 3) << endl;
}

实现2:BFPRT

#include 
using namespace std;

void insertionSort(int a[], int left, int right)
{
    int i, j;

    for(i = left; i < right; i++){
        int tmp = a[i+1];
        for(j = i; j >= 0; j--){
            if (a[j] > tmp)
                a[j+1] = a[j];
            else
                break;
        }
        
        a[j+1] = tmp;
    }
}

int partition(int a[], int l, int r, int pivotId) //对数组a下标从l到r的元素进行划分
{
    //以pivotId所在元素为划分主元
    swap(a[pivotId],a[r]);
    int j = l - 1; //左边数字最右的下标
    for (int i = l; i < r; i++)
        if (a[i] <= a[r])
            swap(a[++j], a[i]);
    swap(a[++j], a[r]);
    return j;
}

int BFPRT(int a[], int l, int r, int id) //求数组a下标l到r中的第id个数
{
    if (r - l + 1 <= 5) //小于等于5个数,直接排序得到结果
    {
        insertionSort(a, l, r); 
        return a[l + id - 1];
    }
 
    int t = l - 1; //当前替换到前面的中位数的下标
    for (int st = l, ed; (ed = st + 4) <= r; st += 5) //每5个进行处理
    {
        insertionSort(a, st, ed); //5个数的排序
        t++; swap(a[t], a[st+2]); //将中位数替换到数组前面,便于递归求取中位数的中位数
    }
 
    int pivotId = (l + t) >> 1; //l到t的中位数的下标,作为主元的下标
    BFPRT(a, l, t, pivotId-l+1);//不关心中位数的值,保证中位数在正确的位置
    int m = partition(a, l, r, pivotId), cur = m - l + 1;
    if (id == cur) return a[m];                   //刚好是第id个数
    else if(id < cur) return BFPRT(a, l, m-1, id);//第id个数在左边
    else return BFPRT(a, m+1, r, id-cur);         //第id个数在右边
}

int main()
{
    int a[] = {2, 6, 3, 5, 4, 23, 56, 78};

    cout << BFPRT(a, 0, 7, 6) << endl;
}


你可能感兴趣的:(算法和数据结构,topk)