虫子 堆排序 基本算法

举报
虫子VV 发表于 2022/06/22 23:49:14 2022/06/22
【摘要】 堆排序 升序 一种非常正常的想法 空间复杂度O(N) 堆升序函数HeapSort 堆排序测试函数 建堆(向上向下为建堆) 向上调整(建大堆) 交换排序&&再向上调整 堆排序代码 堆排序测试 向下调整 排升序 构建小堆 排升序 构建大堆 堆排序 测试堆排序 降序 向上调整 (建小堆) 向下调整(建小堆) 建堆的时间复杂度 堆排序 升序 一种非常正常的想法 空间复杂度O(N)把数组中的元...

堆排序

升序

一种非常正常的想法 空间复杂度O(N)

把数组中的元素全都push到小堆中,然后再取堆顶元素重新给数组,就可以达到升序的效果了

堆升序函数HeapSort

image-20211109215923477

//升序
void HeapSort(HPDataType* a,int n)
{
	HP hp;
	HeapInit(&hp);
	int i = 0;
	//建立一个小堆
	for (i = 0; i < n; i++)
	{
		HeapPush(&hp, a[i]);
	}
	//然后把堆顶的元素重新放到数组里面
	for (i = 0; i < n; i++)
	{
		a[i] = HeapTop(&hp);
		//用完pop掉
		HeapPop(&hp);
	}
	HeapDestroy(&hp);
}

堆排序测试函数

image-20211109220129388

void testHeapSort()
{
	int a[] = { 40,2,0,12,5,454,2323 };
	//堆排序
	HeapSort(a, sizeof(a) / sizeof(a[0]));
	int i = 0;
	for (i = 0; i < sizeof(a) / sizeof(a[0]); i++)
	{
		//把数组里面的元素取出来
		printf("%d ",a[i]);
	}
    printf("\n");
}

建堆(向上向下为建堆)

向上调整(建大堆)

==上面做法一点毛病都没有,但是有要求了,空间复杂度为O(1) 也就是我们不可以在用Heap了==

(这里的插入不是真正的插入,因为这些数据原本就在里面,我们就是在调堆,类似插入)

image-20211110004419158

image-20211110004843299

==看到上面打印的结果我们看到建的是小堆,但是不好的是最小的在下标为0的位置,再次找次小的,从下标为一的位置再构建,这是不行的,因为会破坏结构,所以我们要重头建大堆,然后收尾交换==

image-20211112004113756

//真正玩法
void HeapSort(HPDataType* a, int n)
{
	assert(a && n>=0);
	//把数组a构建成堆
	int i = 0;
	for (i = 0; i < n; i++)
	{
		AdjustUp(a,n,i);
	}
}

交换排序&&再向上调整

image-20211112011348827

堆排序代码
//真正玩法
void HeapSort(HPDataType* a, int n)
{
	assert(a && n>=0);
	//把数组a构建成堆
	int i = 0;
	//向上调整
	for (i = 0; i < n; i++)
	{
		AdjustUp(a,i);
	}
	//根与最后一个数交换并每次都找到次大的数
	int tail = n - 1;
	while (tail)
	{
		Swap(&a[0], &a[tail]);//根与最后一个数交换
		tail--;
		for (i = 0; i <= tail; i++)
		{
			AdjustUp(a, i);
		}
	}	
}
堆排序测试
void testHeapSort()
{
	int a[] = { 40,2,50,12,5,454,2323,};
	//堆排序
	HeapSort(a, sizeof(a) / sizeof(a[0]));
	int i = 0;
	for (i = 0; i < sizeof(a) / sizeof(a[0]); i++)
	{
		//把数组里面的元素取出来
		printf("%d ",a[i]);
	}
	printf("\n");
}

向下调整

排升序 构建小堆

image-20211110204752959

排升序 构建大堆

有种就是这样玩的

image-20211110234106150

堆排序
//真正玩法
void HeapSort(HPDataType* a, int n)
{
	assert(a && n>=0);
	//把数组a构建成堆
	int i = 0;
	////向上调整
	//for (i = 0; i < n; i++)
	//{
	//	AdjustUp(a,n,i);
	//}
	//向下调整
	for (i = (n - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(a, n, i);
	}
	//根与最后一个数交换并每次都找到次大的数
	int tail = n - 1;
	for (i = tail; i > 0; i--)
	{
		Swap(&a[0],&a[i]);//根与最后一个数交换
		AdjustDown(a, i, 0);//向下调整每次都找到次大的数
	}	
}
测试堆排序
void testHeapSort()
{
	int a[] = { 40,2,50,12,5,454,232,30,3,10 };
	//堆排序
	HeapSort(a, sizeof(a) / sizeof(a[0]));
	int i = 0;
	for (i = 0; i < sizeof(a) / sizeof(a[0]); i++)
	{
		//把数组里面的元素取出来
		printf("%d ",a[i]);
	}
	printf("\n");
}

降序

向上调整 (建小堆)

image-20211112012044528

向下调整(建小堆)

image-20211112012356035

建堆的时间复杂度

3.2.3 建堆时间复杂度因为堆是完全二叉树,而满二叉树也是完全二叉树,此处为了简化使用满二叉树来证明(时间复杂度本来看的就是近似值,多几个节点不影响最终结果):

image-20211111230047286

image-20211111230800529

==所以时间复杂度是O(n)==

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。