堆的topk问题

1.正常思路:最大的建立大堆,最小的建立小堆,然后popk次

2.出现问题:n非常大时无法排序

3.新的思路:建立k个数的小堆,然后使用n-k个数依次比较,如果比堆顶的数据大就替换它进堆,再向下调整,最后这个小堆就是最大的前k个

void AdjustDown(int* a, int n, int parent)
{
	//假设左孩子就是最大的
	int child = (parent * 2) + 1;
	while (child < n)
	{
		//筛选左右孩子谁大
//		if(a[child+1]>a[child]),不能这样判断
		//(因为有可能存在右孩子不存在的情况,需要判断一下右孩子是否存在)
		//否则容易出现越界问题
//		if (a[child + 1] > a[child] && child + 1 < n )
// 也不能这样写,这样写跟上面的写法一样了,严格按照顺序
		if (child + 1 < n && a[child + 1] > a[child])
		{
			child++;
		}

		//大孩子和父节点交换
		if (a[child] > a[parent])
		{
			int c=a[child];
			a[child] = a[parent];
			a[parent] = c;
			//交换之后往下走,
			parent = child;
			child = (parent * 2) + 1;
		}
		else
		{
			break;
		}

	}
}


void topk1(int* a, int n, int k)
{
	assert(a != NULL);
	assert(k > 0);

	int* topk = (int*)malloc(sizeof(int) * 2*k);
	assert(topk);
	for (int i = 0; i < k; ++i)
	{
		topk[i] = a[i];
	}

	//1.先建堆,向下调整建堆,现在是建小堆,那就找最大的前k个
	//把前k个抓起来,建立一个k大小的堆

	for (int i = (k - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(topk, k, i);
	}

	//2.然后从第k个开始,往堆里面插入
	int j = k;
	while (j < n)
	{
		if (a[j] 

最小建立大堆,最大建立小堆

你可能感兴趣的:(数据结构,数据结构)