#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;
}
求100W个数中的前K个最大的数
最新推荐文章于 2024-02-27 22:45:58 发布
