数据结构——堆排序

课前了解:

一、二叉树:在树的基础上,要求任何一个节点的度不能超过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 直到树中只剩下一个节点为止
 }
相关推荐
有同事要进步11 分钟前
Leecode第68题:x的平方根
java·数据结构·算法
Pniubi29 分钟前
HashMap扩容全流程
java·开发语言·数据结构
by2099921 小时前
哈希表——快速找到数据:冲突、删除与扩容的实现
数据结构·c++·哈希算法·散列表
Code_Solitude21 小时前
c语言:关于qsoet函数知识点
c语言·数据结构·算法
Pniubi1 天前
快速排序(力扣基础)(递归)
java·数据结构·算法
inrichtt1 天前
第八课时:SPI总线揭秘:四线全双工通信的奥
c语言·数据结构·stm32·单片机·嵌入式硬件
HPtiger1 天前
数据结构——选择排序
数据结构·算法·排序算法
丑梨数据1 天前
信创环境里跑文档工具:格式兼容与本地合规的几个坑
数据结构·人工智能·算法·决策树·排序算法
烂蜻蜓1 天前
Pandas入门教程(四):Series数据结构——创建、索引与常用方法
数据结构·pandas
CS创新实验室2 天前
一棵树怎么做到“自平衡还不太费力“?——红黑树的旋转与染色
数据结构·算法·红黑树·408·计算机考研