数据结构——堆排序

课前了解:

一、二叉树:在树的基础上,要求任何一个节点的度不能超过2(换句话说,任何一个节点最多有两个孩子)

二叉树的特殊形态:

1.满二叉树:

由2^k-1个节点组成的有一颗k层的二叉树,这个二叉树就是满二叉树

这就是满二叉树

2.完全二叉树:

口语:相较于满二叉树可以缺少节点,但是只能紧着最下面一层,从右至左的缺少节点,不能跳着缺少。

官方:

对满二叉树,从根节点出发,从上至下,从左至右,依次进行编号

有n个节点组成的一颗K层二叉树,其中n个节点的编号,和其K层满二叉树中的1-》n编号相同

满二叉树也是完全二叉树。

二、大顶堆和小顶堆:

大顶堆和小顶堆都是完全二叉树

大顶堆:任意一个节点都大于它的左右孩子

小顶堆:任何一个节点都小于它的左右孩子

思想:

假设现在有一个一维数组

我们现在臆想将这个数组想象为一个完全二叉树

父推子:

完全二叉树怎么调整为大顶堆:

1.对待排序序列构造出来的完全二叉树,先由内到外的调整一遍(换句话说,就是从最后一个非叶子节点作为根节点的子树开始,从右至左,从下至上)

五个非叶子节点,所以有五颗子树需要调整:

💙 蓝色框

💚 绿色框

空白格子没有左右孩子就触底了 就将我们原本的82放回到空白格子

🟠 橙色框

💖粉色框

将98 移上去之后剩余空白格子 观察空白格子左后孩子有没有比17更大的数据并且是这几个数据中最大的数 如果有就将这个最大的数据放到空白格子 如果没有就将数据17 放到该空白格子

🔴红色框

第一步:将找到的最大值(就是大顶堆的根节点)与最后一个值进行交换

第二步:头尾交换 让尾断开连接

第三步:调整最外层 进行排序

第四步:反复执行2 3步 直到树中只剩下一个节点位置

最终图案为:

cs 复制代码
//单独调整函数(单独调整一次 给定的框框
void Heap_Adjust(int arr[], int start, int end) {
	assert(arr != NULL);
	//将此时要调整的框框(子树)的根节点取出来 放到tmp中 防止被覆盖
	int tmp = arr[start];


	//再申请一个变量 用来指向空白格子的较大孩子 默认先指向空白格子 左孩子
	int maxchild = start * 2 + 1;
	//进入while循环 循环条件是空白格子的左孩子存在
	while (maxchild <= end) {
		//如果右孩子存在 且值还大于左孩子 则修正maxchild 的指向
		if (maxchild + 1 <= end) {
			if (arr[maxchild + 1] > arr[maxchild]) {
				maxchild = maxchild + 1;
			}

			//此时if执行结束 maxchild一定指向此时这个空白格子的较大孩子
		}

		//较大孩子找到了 则让其和tmp的值进行比较 如果大于tmp的值 则较大孩子上移
		// 如果可以找到较大孩子 和tmp的值进行比较 如果大于tmp的值 较大孩子上移
		if ( arr[maxchild] > tmp) {
			//把较大孩子值上移到空白格子的位置
			arr[start] = arr[maxchild];
			//此时新出现的空白格子就是刚才挪动的较大孩子的位置 让start同步过来
			start = maxchild;
			//在再让maxchild同步为新的空白格子start的左孩子 再次进入while循环判断
			maxchild = start * 2 + 1;

		}
		else {//较大孩子找到了但是其值小于tmp的值则触发退出情况
			break;//情况1:较大孩子并不大于tmp 将tmp挪回去

			
			//情况2:触底 空白格子没有一个孩子 则也该将tmp挪动回去
		}
	}
	arr[start] = tmp;
	
	//较大孩子上移之后原先的位置就出现了新的空白格子,以同样的逻辑进行

	//什么时候将tmp挪回去
		//情况1 :空白格子的较大孩子不大于temp
		//情况2:空白格子没有一个孩子
}
void Heap_Sort(int arr[], int len) {
  //直接将其从内向外的调整一遍(从最后的一个非叶子节点作为根节点的子树开始 由右至左 由下至上
	for (int i = (len - 1 - 1) / 2;i >= 0;i--)//i用来指向要调整的根节点
	{
		//调用单次调整
		Heap_Adjust(arr, i, len-1);
	}

    //首尾交换 然后断开尾巴连接(此时调整好的大顶堆的根节点就是其最大值
	for (int j = 0;j < len - 1;j++)//控制首尾交换的次数 n个值 交换
	{
		int tmp = arr[0];
		arr[0] = arr[len - 1];
		arr[len - 1 - j] = tmp;
		Heap_Adjust(arr, 0, len - 1 - j - 1);


			//只需要调整最外层框框(只调整一次最大的这棵树)
	}
	
	//反复执行23 直到树中只剩下一个节点为止
 }
相关推荐
Logic1014 小时前
C语言/数据结构位运算题解:异或XOR找出多任务下载器中的“独特下载速度“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质
yexianglunbai7 小时前
Redis 详解:从核心数据结构到高可用架构实战
数据结构
bro_Java6667 小时前
《栈与队列:数据结构的“双生花”》
java·数据结构·编辑器
sogw-三叶草️8 小时前
LeetCode 989. 数组形式的整数加法
数据结构·算法
yi0119 小时前
DAY 14: LeetCode 394. 字符串解码|递归和栈到底怎么处理嵌套?
数据结构·笔记·python·算法·leetcode
张小姐的猫10 小时前
【AI大模型接入SDK】 —— 前端页面 & 项目总结与拓展
前端·数据结构·数据库·c++·人工智能·chatgpt
sunburn-11 小时前
Java 排序算法详细教学:从冒泡排序到快速排序
java·开发语言·数据结构·ide·算法
bksczm12 小时前
零基础面试题1
jvm·数据结构·算法
sogw-三叶草️12 小时前
LeetCode206. 反转链表
数据结构·链表
careathers12 小时前
【数据结构】二叉树
数据结构·算法