数据结构|排序算法(三)堆排序

二、堆排序

堆是一种特殊的完全二叉树,分为大根堆和小根堆。

大根堆的每个节点的值都大于或等于其左右子节点的值,小根堆则相反,每个节点的值都小于或等于其左右子节点的值。(大根堆小根堆只看父子关系)

堆排序的基本思想是将待排序的序列构建成一个堆,然后依次取出堆顶元素并调整堆,直到整个序列有序。

1.算法思想

建堆:将给定的数组构建成一个大根堆(或小根堆)。从最后一个非叶子节点开始,依次向上调整每个节点,使其满足堆的性质。

交换元素:将堆顶元素与堆的最后一个元素交换位置,此时堆顶元素是当前堆中的最大(或最小)值,将其取出,放到已排序序列的末尾。

调整堆:交换元素后,堆的性质可能被破坏,需要对剩余的元素重新调整堆,使其再次满足堆的性质。重复步骤 2 和 3,直到堆中只剩下一个元素,此时整个数组已经有序。

1->调整成大根堆

(1)从最后一棵子树开始,从后往前调整

(2)每次调整,从上往下

(3)整体调整成大根堆

具体调整:

定义一个临时变量tmp,把根放到tmp里,找左右孩子的最大值,和tmp比较,如果比tmp大,则放到根的位置,继续递归比较新的左右孩子的最大值

调整顺序:
调整子树:调整完成:

2->根和待排序的最后一个交换

根是最大的,交换后则视作有序

3->再次调整成大根堆

2.代码实现

复制代码
//堆排序
 
void HeapAdjust(int* arr, int start, int end)
{
	int tmp = arr[start];
	for (int i = 2 * start + 1; i <= end;i=2*i+1)//从上往下
	{
		if (i < end && arr[i] < arr[i + 1])//如果有右孩子,且左孩子的值小于右孩子
		{
			i++;
		}//i一定是左右孩子的最大值
		if (arr[i] > tmp)
		{
			arr[start] = arr[i];
			start = i;
		}
		else
		{
			break;
		}
	}
	arr[start] = tmp;
}
 
void HeapSort(int* arr, int len)
{
	//第一次建立大根堆(从后往前,多次调整)//根分别为4 3 2 1的子树
	for (int i = (len-1-1)/2; i >= 0; i--)//i的初值与结点总数有关,i=总结点数len-根-
	{
		HeapAdjust(arr, i, len - 1);
	}
	//每次将根和待排序的最后一个交换,然后再次调整(注意是待排序部分)
	int tmp;//用于交换
	for (int i = 0; i < len - 1; i++)
	{
		tmp = arr[0];
		arr[0] = arr[len - 1 - i];
		arr[len - 1 - i] = tmp;
 
		//再次调整
		HeapAdjust(arr, 0, len - 1 - i - 1);
	}
	
	return;
}

3.复杂度分析

建立大根堆的时间复杂度:O(n)

每次调整大根堆时间复杂度:O(logn),调整次数n-1次,总时间复杂度O(nlogn)

综合建堆和排序两个阶段,堆排序的时间复杂度为O(n+nlogn),通常简化为O(nlogn)。这是堆排序的平均时间复杂度;

空间复杂度O(1);

不稳定

相关推荐
用户298698530143 小时前
Java 实现 Word 文档加密与权限解除
java·后端
Yeats_Liao3 小时前
14:Servlet中的页面跳转-Java Web
java·后端·架构
未秃头的程序猿3 小时前
告别"if-else地狱"!Java 21模式匹配,代码优雅了10倍
java·后端·面试
鹤望兰6754 小时前
字节跳动国际支付-后端开发-三面面经
java
Flittly4 小时前
【AgentScope Java新手村系列】(14)人机交互
java·spring boot·spring
RainCity4 小时前
Java Swing 自定义组件库分享(十二)
java·笔记·后端
吃饱了得干活20 小时前
Spring Cloud Gateway 微服务网关:路由、断言、过滤器
java·spring cloud
lwx5728021 小时前
探秘InnoDB:搞懂它的内存、线程、磁盘与日志刷盘策略
java·后端
Flynt1 天前
从Spring Boot 4.0升到4.1,我在Maven和gRPC上栽了跟头
java·spring boot·后端
plainGeekDev1 天前
Activity 间传值 → Navigation 参数
android·java·kotlin