基于Visual C++2013拆解世界五百强面试题--题10-找出N个数种最大的K个数

有一亿个整数,请找出最大的 1000 个,要求时间越短越好, 空间占用越好越好。


如果不考虑时间效率,很容易想到解决方法,我们只需存储前一千个数,

然后依次读入后面的数和这一千个数组比较,替换其中比较小的数即可,

但是这样时间复杂度比较高,如果用二叉堆实现,直接可以替换1000个数中最小的数字,

而消耗的时间大多数话费在二叉堆插入中,二叉堆的插入复杂度为Olog(N),比较理想。


由于题目中数目太大,代码实现中是用户不停输入数字,然后程序找出前十个最大的数。


下面我们来实现它:


#include <stdio.h> 

//这个函数调整对数组中第n个元素的位置
void HeapAdjust(int array[], int n, int length)
{
	int Child;
	for (int i = n; i * 2 <= length; i = Child)
	{
		Child = i * 2;
		if (Child + 1 <= length && array[Child] < array[Child + 1])
			Child++;
		//如果较大的子节点大于父节点则交换位置
		if (array[i] < array[Child])
		{
			int Temp = array[i];
			array[i] = array[Child];
			array[Child] = Temp;
		}
		else
		{
			break;
		}
	}
}

void HeapSort(int array[], int length)
{
	//调整前半部分,保证了最大的值都在前半部分
	for (int i = length / 2; i > 0; i--)
	{
		HeapAdjust(array, i, length);
	}
	for (int i = length-1; i > 0; i--)
	{
		//将最大的数移动到尾部
		int Temp = array[1];
		array[1] = array[i+1];
		array[i+1] = Temp;
		//除去尾部后,调整第一个元素位置
		HeapAdjust(array, 1, i);
	}
}

void HeapAdjustLittle(int array[], int num, int length)
{
	//如果输入的数小于这些数,直接返回
	if (num < array[1])
	{
		return;
	}

	//如果输入的数大于数组中最小的数,则赋值,然后调整堆数组
	array[1] = num;
	int Child;
	for (int i = 1; i * 2 <= length; i = Child)
	{
		Child = i * 2;
		if (Child + 1 <= length && array[Child] > array[Child + 1])
			Child++;
		//如果较小的子节点大于父节点则交换位置
		if (array[i] > array[Child])
		{
			int Temp = array[i];
			array[i] = array[Child];
			array[Child] = Temp;
		}
		else
		{
			break;
		}
	}
}

//打印出数组内容
void PrintArray(int array[], int size)
{
	printf("最大的前%d个数:\n", size);
	for (int i = 0; i < size; i++)
	{
		printf("%3d", array[i]);
	}
	printf("\n");
}

int myarray[] = { 0, 1, 9, 2, 8, 3, 7, 4, 6, 5 , 10};

int main()
{
	//将前十个数进行一次堆排序,并输出结果
	HeapSort(myarray, sizeof(myarray) / 4 - 1);
	PrintArray(myarray + 1, sizeof(myarray) / 4 - 1);

	//输入数字,打印出前十个最大的数
	while (1)
	{
		int num = 0;
		scanf("%d", &num);
		HeapAdjustLittle(myarray, num, sizeof(myarray) / 4 - 1);
		PrintArray(myarray + 1, sizeof(myarray) / 4 - 1);
	}

	return 0;
}



运行结果:




大家可以通过调试程序更好的理解程序运行,

将光标移至函数头,然后按下F9,打一个断点,按下F5程序即停止在断点处,如下图所示:



现在我们可以按F10单步调试,或者F11(可以跟进函数)。在调试窗口中看每一个变量的改变:



如果有什么问题和疑问可以在下面留言互相探讨。

原题我已经上传到这里了http://download.csdn.net/detail/yincheng01/6461073 ,

解压密码为 c.itcast.cn



你可能感兴趣的:(基于Visual C++2013拆解世界五百强面试题--题10-找出N个数种最大的K个数)