求100W个数中的前K个最大的数

#include<iostream>
#include<windows.h>
using namespace std;
//挨个遍历排序:100w个数太多,内存不够,而且遍历排序效率太低
//建大堆:只能选出最大的那个数
//可选方案:建K个数的小堆
//首先取这100w个数中的前K个数建立最小堆,即长度为K的数组的首元素为最小的元素
//然后依次取剩下的元素,和首元素进行比较,如果比首元素大则替换,然后继续排最
//小堆,让最小的数排在首元素位置,继续比较
#define  M 100000
#define  K 10
向下调整成最小堆
void AdjustDown(int parent, int arr[])
{
    int child = parent * 2 + 1;
    while (child<K)
    {
        if (child+1<K&&arr[child]>arr[child + 1] )//找结点左右较小的孩子,注意右孩子不能为空
        {
            child += 1;
        }
        if (arr[parent]>arr[child])//找结点左右较小的孩子
        {
            swap(arr[parent], arr[child]);
            parent = child;
            child = parent * 2 + 1;//重新当成一棵树访问
        }
        else
            break;
    }
}
//取出前K个数并保存——生成最小堆——M中剩下的数和堆顶元素比较
void GetKMaxNum(int array[], int top[])
{  
    //取出100W个数中前K个数保存到top数组
    for (int idx = 0; idx < K; idx++)
    {
        array[idx] = top[idx];
    }
    //将top数组生成最小堆
    for (int idx = (K - 2) >> 1; idx>=0; --idx)
    {
        AdjustDown(idx, top);//从倒数第一个非尾结点的位置开始调整
    }
    //取array里面剩下的数和top里面的堆顶元素进行比较,如果比堆顶元素大,则替换,
    //然后再次调整成最小堆,则堆里的元素是最大的前K 个元素
    for (int idx = K ; idx <M; ++idx)
    {   
        if (top[0] < array[idx])
        {
            top[0] = array[idx];
            AdjustDown(0, top);//从首元素位置继续调整,使之成为最小堆
        }
    }
}
void Print(int top[])
{
    int count = 0;
    for (int i = 0; i < K; i++)
    {
        cout << top[i] << "   ";
        count++;
        if (count % 5 == 0)
        {
            cout << endl;
        }
    }
    cout << endl;
}
void Test()
{
    int array[M] = { 0 };
    int top[K] = { 0 };
    for (int i = 0; i < M; i++)
    {
        array[i] = i;
    }
    array[10000] = 9999999;
    array[M-100] = 199999;
    array[M-5] = 22222222;
    GetKMaxNum(array, top);
    Print(top);
}

int main()
{
    Test();
    system("pause");
    return 0;
}

这里写图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值