0
点赞
收藏
分享

微信扫一扫

堆排序详解+TOP-K问题

kiliwalk 2022-04-13 阅读 35

上上篇链接: 堆的实现+堆排序_i跑跑的博客-CSDN博客


 


目录

分析上上篇堆排序

思路

时间空间复杂度

优化堆排序 

向上调整建堆

分析

图解

时间复杂度

代码实现

 向下调整建堆

 分析

图解

时间复杂度 

代码实现

总结 

排序 

思路分析

排序思想

降序建小堆证明

代码实现

小堆变大堆:

TOP-K问题

什么是TOP-K问题?

思路

时间复杂度

空间复杂度

代码实现

随机数据测试 

添加排序程序


分析上上篇堆排序

上篇介绍二叉树笔记在最后实现了一个简单的堆排序:

+

void HeapSort(int* a,int size)
{
	HP hp;
	HeapInit(&hp);

    //时间复杂度O(N*logN)
	for (int i = 0;i<size;i++)
	{
		HeapPush(&hp,a[i]);
	}
	HeapPrint(&hp);
	int j = 0;

    //时间复杂度O(N*logN)
	while (!HeapEmpty(&hp))
	{
		a[j] = HeapTop(&hp);
		j++;
		HeapPop(&hp);
	}
	HeapDestroy(&hp);
}


 优化堆排序 

之前是先创建堆,再把数组进行插入,这次我们直接在数组里面进行建堆,令数组变成堆,使堆排序算法的空间复杂度为O(1)

向上调整建堆

为了方便讲解,将堆向上调整在这里展示出来,以建小堆为例

代码实现

//向上调整
//建小堆为例
void Up(HPDataType* a,size_t child)
{
	size_t 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 HeapSort(int* a,int size)
{
	//向上调整建堆
	//分析后是件复杂度为O(N*logN)
	for (int i = 1;i<size;i++)
	{
		Up(a,i);
	}
}

 向下调整建堆

代码实现

//建小堆为例
void Down(HPDataType* a, size_t parent, size_t size)
{
	size_t child = parent * 2 + 1;
	while (child < size)
	{
		if (child + 1 <size && a[child+1] < a[child])
		{
			child++;
		}
		if (a[child] < a[parent])
		{
			swap(&a[child],&a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

void HeapSort(int* a,int size)
{
	//向下调整建堆
	//分析后是件复杂度为O(N+logN)=O(N)

	for (int i = (size-1-1)/2; i>=0; i--)
	{
		Down(a,i, size);
	}
}

总结 

排序 



这样堆排序就可以实现啦

决定升序还是降序,创建大堆或小堆即可


 

TOP-K问题

什么是TOP-K问题?

思路

代码实现

//TOP-K问题
void PrintTopK(int* a, int n, int k)
{
	// 1. 建堆--用a中前k个元素建堆
	int* kHeap = (int*)malloc(sizeof(int)*k);
	if (kHeap == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}

	//将前k个数插入数组kHeap中
	for (int i = 0;i<k;i++)
	{
		kHeap[i] = a[i];
	}

	//在数组里面建小堆
	for (int i = (k - 1 - 1) / 2; i >= 0; i--)
	{
		Down(a, i, k);
	}

	// 2. 将剩余n-k个元素依次与堆顶元素交换,不满则则替换
	for (int i = k;i<n;i++)
	{
		if (a[i]>kHeap[0])
		{
			kHeap[0] = a[i];
			Down(kHeap,0,k);
		}
	}

	// 3. 打印最大或最小的前k个
	for (int j = 0;j<k;j++)
	{
		printf("%d ",kHeap[j]);
	}
	printf("\n");


	free(kHeap);
}

随机数据测试 

添加排序程序 

//TOP-K问题
void PrintTopK(int* a, int n, int k)
{
	// 1. 建堆--用a中前k个元素建堆
	int* kHeap = (int*)malloc(sizeof(int)*k);
	if (kHeap == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}

	//将前k个数插入数组kHeap中
	for (int i = 0;i<k;i++)
	{
		kHeap[i] = a[i];
	}

	//在数组里面建小堆
	for (int i = (k - 1 - 1) / 2; i >= 0; i--)
	{
		Down(a, i, k);
	}

	// 2. 将剩余n-k个元素依次与堆顶元素交换,不满则则替换
	for (int i = k;i<n;i++)
	{
		if (a[i]>kHeap[0])
		{
			kHeap[0] = a[i];
			Down(kHeap,0,k);
		}
	}

	// 3. 排序
	//最后一个数据的下标
	size_t end = k - 1;
	while (end>0)
	{
		swap(&kHeap[0], &kHeap[end]);
		Down(kHeap, 0, end);
		end--;
	}


	// 4. 打印排序后的前k个
	for (int j = 0;j<k;j++)
	{
		printf("%d ",kHeap[j]);
	}
	printf("\n");


	free(kHeap);
}

堆排序和TOP-K问题的笔记到这里就结束啦,欢迎各位伙伴在留言区里交流评价噢,求赞求赞求赞!!! 

 

举报

相关推荐

0 条评论