N个数中找出最大的K个数

题目描述:

有很多个(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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值