【排序算法】——— 堆排序总结

本文详细介绍了堆排序算法的思想,包括如何初始化堆和通过交换数据进行排序的过程。堆排序是一种基于二叉堆的数据结构进行排序的方法,其时间复杂度为O(N*lgN)。虽然效率较高,但堆排序并不稳定,因为相等元素的相对位置可能会改变。文章还提供了代码示例和对堆排序稳定性的分析。
摘要由CSDN通过智能技术生成

【1】堆排序算法思想

堆是具有以下性质的完全二叉树

  • 我们假设有一棵完全二叉树,在满足作为完全二叉树的基础上,对于任意一个拥有父节点的子节点,其数值均不小于父节点的值;这样层层递推,就是根节点的值最小,这样的树,称为小根堆。
  • 同理,又有一棵完全二叉树,对于任意一个子节点来说,均不大于其父节点的值,如此递推,就是根节点的值是最大的,这样的树,称为大根堆。

我们接下来看一下如下这个数组的排序思路
数组{20,30,90,40,70,110,60,10,100,50,80} n=11
在这里插入图片描述

初始化堆

在堆排序算法中,首先要将待排序的数组转化成二叉堆。
下面演示将数组{20,30,90,40,70,110,60,10,100,50,80}转换为最大堆{110,100,90,40,80,20,60,10,30,50,70}的步骤。

【1】i=4时

为什么要从i=11/2-1=4开始呢?我们发现i为4,3,2,1,0的时候他们都是有孩子的结点。
在这里插入图片描述a[4]左孩子是a[9],a[4]右孩子是a[10],调整时选择左右孩子中较大的一个孩子进行比较如果a[4]小则交换,否则不交换。上边例子中a[4]小于较大的a[10]=80,所以交换a[4]和a[10]

【2】i=3时
在这里插入图片描述a[3]左孩子是a[7],a[3]右孩子是a[8],调整时选择左右孩子中较大的一个孩子a[8]=100进行比较如果a[4]小则交换,否则不交换。上边例子中a[3]=40小于较大的孩子a[8]=100,所以交换a[3]和a[8]
【3】i=2时
在这里插入图片描述a[2]左孩子是a[5],a[2]右孩子是a[6],调整时选择左右孩子中较大的一个孩子a[5]=110进行比较如果a[2]小则交换,否则不交换。上边例子中a[2]=90小于较大的孩子a[5]=110,所以交换a[2]和a[5]
【4】i=1时
在这里插入图片描述a[1]左孩子是a[3],a[1]右孩子是a[4],调整时选择左右孩子中较大的一个孩子a[3]=100进行比较如果a[1]小则交换,否则不交换。上边例子中a[1]=30小于较大的孩子a[3]=100,所以交换a[1]和a[3],交换完之后a[3]=30小于他的右孩子a[8]=40,所以继续交换完成

【5】i=0时
在这里插入图片描述a[0]左孩子是a[1],a[0]右孩子是a[2],调整时选择左右孩子中较大的一个孩子a[2]=110进行比较如果a[0]小则交换,否则不交换。上边例子中a[0]=20小于较大的孩子a[2]=110,所以交换a[0]和a[2],交换完成之后a[2]又小于他的较大孩子a[6]=90,则继续交换才能完成

交换数据进行排序

调整完毕,就得到了最大堆。此时,数组{20,30,90,40,70,110,60,10,100,50,80}也就变成了{110,100,90,40,80,20,60,10,30,50,70}。
在这里插入图片描述上面是当n=10时,交换数据的示意图。
我们知道大根堆的根节点a[0]元素永远是最大的

当n=10时,首先交换a[0]和a[10],使得a[10]是a[0]到[10]之间的最大值;然后,调整a[0]到a[9]使它称为最大堆。交换之后:a[10]是有序的!

当n=9时, 首先交换a[0]和a[9],使得a[9]是a[0]到[9]之间的最大值;然后,调整a[0]到[8]使它称为最大堆。交换之后:a[9]到[10]是有序的!

依此类推,直到a[0…10]是有序的。

【2】代码示例

//============================递归==================================
#include<iostream>
#include<vector>
using namespace std;

void adjust(vector<int>&vec, int len, int index)	//调整函数
{
   
	int left = 2 * index + 1;	//左孩子
	int right = 2 * index + 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值