题目描述:
有很多个(N个)无序的数,我们姑且假定它们各不相等,怎么选出其中最大的若干个(k个)数呢?
1.N=100, K = 10的时候怎么处理?2. N=1000, K = 100呢?
3. N=1亿亿个, K = 100呢?
如果这些数是整数的话,怎么处理?如果是浮点数呢?
如果这些数是整数,并且存在上界呢?
如果将题目中的"各不相等"这个条件去掉呢? 处理方式又会出现什么变动么?
include<stdio.h>
#include<string.h>
#include<assert.h>
//递归调整堆,将元素heap[startIdx]加入堆中
void maintainHeap(int heap[], int startIdx, int size)
{
int minIdx = startIdx;
int min = heap[startIdx];
int leftNode = minIdx*2 + 1;
int rightNode = leftNode + 1;
if(leftNode < size)
{
if(min > heap[leftNode])
{
minIdx = leftNode;
min = heap[leftNode];
}
if(rightNode < size && min > heap[rightNode])
{
minIdx = rightNode;
min = heap[rightNode];
}
if(minIdx != startIdx)
{
int tmp = heap[startIdx];
heap[startIdx] = heap[minIdx];
heap[minIdx] = tmp;
maintainHeap(heap, minIdx, size);
}
}
return ;
}
//建立堆, 即将所有的非叶子结点都从上到下调整一下,加入堆中
void makeHeap(int heap[], int size)
{
for(int i = size/2 -1; i >= 0; i--)
maintainHeap(heap,i,size);
return;
}
void topNWithHead(int input[], int output[], int inputSize, int outputSize)
{
assert(input && output && inputSize>0 && outputSize>0);
//将前outputSize个元素建成小根堆
memcpy(output,input, outputSize * sizeof(int));
makeHeap(output, outputSize);
//将数组中后续的元素依次判断,是否要加入堆中,加入后调整堆
for(int i = outputSize+1; i < inputSize; i++)
{
if(input[i] > output[0])
{
output[0] = input[i];
maintainHeap(output, 0, outputSize);
}
}
return;
}
//输出数组元素
void PrintArray(int a[], int size)
{
printf("{ %d", a[0]);
for(int i = 1; i < size; i++)
printf(", %d", a[i]);
printf(" }\n");
}
//用打擂台法找到最大的数
int maxInArray(int a[], int size)
{
int max = a[0];
for(int i = 1; i < size; i++)
if(max < a[i]) max = a[i];
return max;
}
//用打擂台法找到最大的两个数
void max2InArray(int a[], int size, int* max1, int* max2)
{
if(size == 1)
{
*max1 = *max2 = a[0];
return;
}
if(a[0]<a[1])
{
*max1 = a[1];
*max2 = a[0];
}
else
{
*max1 = a[0];
*max2 = a[1];
}
for(int i = 2; i < size; i++)
{
if(a[i] > *max1)
{
*max2 = *max1;
*max1 = a[i];
}
else if(a[i] > *max2)
{
*max2 = a[i];
}
}
}
int main()
{
int input[] = {6,7,8,9,10,1,3,19,22,13,5,4,23,17,11};
int output[5];
topNWithHead(input,output, sizeof(input)/ sizeof(int), sizeof(output)/sizeof(int));
printf("原集合为:\n");
PrintArray(input,sizeof(input)/sizeof(int));
int max1,max2;
printf("最大的数为: %d\n",maxInArray(input,sizeof(input)/sizeof(int)));
max2InArray(input,sizeof(input)/sizeof(int), &max1, &max2);
printf("最大的两个数为: %d, %d\n", max1, max2);
printf("前%d大的数字为:\n", sizeof(output)/sizeof(int));
PrintArray(output,sizeof(output)/sizeof(int));
return 0;
}
============================================
运行结果:
原集合为:{ 6, 7, 8, 9, 10, 1, 3, 19, 22, 13, 5, 4, 23, 17, 11 }
最大的数为: 23
最大的两个数为: 23, 22
前5大的数字为:{ 13, 17, 22, 19, 23 }
Press any key to continue