堆排序-TOP-K问题(C语言数据结构)

前言:

        学习堆及堆排序,认识到堆的内部原理,这时候就应该运用在实体场景。

        例如:全校有2000人,如何帅选出成绩最好的前10名。

                   帅选出全球前100所最具潜力的公司等等。

TOP-K问题:

如何创造出多个数据?

        在32位机器上整型占4个字节,电脑一般自带内存是8GB或者16GB,也就是最多存储

2,147,483,648个整型数据。

        如果一次性的数量比较大超过了21亿,此时就需要将数据存储在硬盘上面,通常硬盘的内存会比较大,当我们需要的时候在硬盘上去读取数据即可。

将数据写入文件中:

        这里涉及到如何将数据写入文件中,也就是文件相关的操作:文件操作(1)(C语言版)-CSDN博客

        可以根据以前写的文章进行复习。

在这里我们将数据写入文件中用fprintf,读取时用fscanf。(运用格式化读写会比较方便!)

将文件打开并将数据写入:

void CreatData()
{
	srand((unsigned int)time(NULL));
	char name[] = { "data.txt" };
	int arr[100000];
	int a = 0;
	FILE* data = fopen(name, "w");
	if (data == NULL)
	{
		perror("fopen ::error");
		exit(-1);
	}
	for (int i = 0; i < 100000; i++)
	{
		a = (rand() + i) % 10000;
		arr[i] = a;
	}
	for (int i = 0; i < 100000; i++)
	{
		fprintf(data,"%d\n",arr[i]);
	}
	fclose(data);
}

TOP-K思路:

        因为小堆的最上层是最小的,如果没有比堆里面最小的大,那么就是最大的10个

主要思路还是“沉底思想”

代码:

void AdjustUp(HPDataType* a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[child] < a[parent])
		{
			swap(&a[child], &a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}
void AdjustDown(HPDataType* a, int size, int parent)
{
	//假设最大的孩子的值是左孩子对应的数值
	int childmax = (parent * 2) + 1;
	while (childmax < size)
	{
		//如果右有孩子并且右孩子的值是大于左孩子将最大的孩子换成右孩子
		if (childmax + 1 < size && a[childmax + 1] < a[childmax])
		{
			childmax = childmax + 1;
		}
		if (a[parent] > a[childmax])
		{
			swap(&a[parent], &a[childmax]);
			parent = childmax;
			childmax = (parent * 2) + 1;
		}
		else
		{
			break;
		}
	}
}
void swap(HPDataType* a, HPDataType* b)
{
	HPDataType c = 0;
	c = *a;
	*a = *b;
	*b = c;
}
void CreatData()
{
	srand((unsigned int)time(NULL));
	char name[] = { "data.txt" };
	int arr[100000];
	int a = 0;
	FILE* data = fopen(name, "w");
	if (data == NULL)
	{
		perror("fopen ::error");
		exit(-1);
	}
	for (int i = 0; i < 100000; i++)
	{
		a = (rand() + i) % 10000;
		arr[i] = a;
	}
	for (int i = 0; i < 100000; i++)
	{
		fprintf(data,"%d\n",arr[i]);
	}
	fclose(data);
}
void test3()
{
	//创造数据
	CreatData();
	FILE* data = fopen("data.txt", "r");
	if (data == NULL)
	{
		perror("fopen :error");
		exit(-1);
	}
	int k = 10;
	//创建堆
	int* heap = (int*)malloc(sizeof(int) * k);
	if (heap == NULL)
	{
		perror("heap::error");
		exit(-1);
	}
	//建立k个数的小堆
	for (int i = 0; i < k; i++)
	{
		fscanf(data,"%d",&heap[i]);
		AdjustUp(heap,i);
	}
	//比较所有的数,如果有大于堆顶的将覆盖,并向下调整
	int a = 0;
	while (fscanf(data,"%d",&a) != EOF)
	{
		if (heap[0] < a)
		{
			heap[0] = a;
			AdjustDown(heap, k, 0);
		}
	}
	for (int i = 0; i < k; i++)
	{
		printf("%d ", heap[i]);
	}
	free(heap);
	heap = NULL;
	fclose(data);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值