堆排序算法

内容仅供个人复习

堆与堆排序

堆的定义

1.堆是一个完全二叉树
2.完全二叉树是指可能缺少右节点的满二叉树,或者最后一层的上一层,缺少右侧子节点的二叉树。
3.最大堆中的父节点大于子节点,最小堆中的父节点小于子节点

堆的特性

1.当前节点为i的父节点,子节点为 [2i]/[2i+1]
2.当前节点为i的子节点,父节点为 [i/2]
3.堆的父节点个数为:[i/2]
注释:( [] 向下取整)

堆的C语言实现

一段数组构造:

数据47139258
序号12345678

上面这段数组中 4 7 1 3 9 2 5 8 使用最大堆完成排序
假设将上述数组放入在a[10]中,a[0] 不存放,从a[1]开始计数,上述正好是
a[1]-a[8]
设置 N = 8 序号
i 为当前序号数
堆如下:
4
7 1
3 9 2 5
8

根据最大堆原理以及寻找父节点的办法,本次序号为8,N/2=4,取向下为4,找到父节点序号为4的节点,也就是数据3,此后对序号为4的节点,找到最大的子节点,当前仅有数据8一个,进行父节点与最大子节点比较后,将父节点与最大子节点进行交换如下:

4
7 1
8 9 2 5
3
在第一次调整以后,移动至下一个父节点处,也就是8/2-1=3,即为序号3的节点,也就是数据1处,同上述处理后,得到结果为

4
7 5
8 9 2 1
3
随后再次移动到新的父节点,3-1=2,即序号为2的节点,数据为7处,同上述处理后,得到结果为
4
9 5
8 7 2 1
3
随后继续执行移动,2-1=1,序号为1的节点,数据为4处,同上述处理后,得到的结果为
9
4 5
8 7 2 1
3
此时,由于是最后一个父节点,说明已经找出了最大值,也就是 9
之后,将9与最后一个数据的位置对换,也就是a[1]与a[N]交换

3
4 5
8 7 2 1
9
将 9 去掉,–N,N的数量下降1,也就是N=7
3
4 5
8 7 2 1
对该堆继续使用之前的办法,进行最大值提取,序号为7,7/2=3,也就是从数据为5的父节点开始排
5:–3(父节点序号)
3
4 5
8 7 2 1
4:–2
3
8 5
4 7 2 1
3:–1
8
3 5
4 7 2 1
此时 的父节点不能再往下减少,因此,已经取到最大值,开始调换a[1]与a[N]的位置,
1
3 5
4 7 2 8
随后,同上所述,N的序列再次减一,N=6
1
3 5
4 7 2

对该堆继续使用之前的办法,进行最大值提取,序号为6,6/2=3,也就是从数据为5的父节点开始排
5:–3
1
3 5
4 7 2
3:–2
1
7 5
4 3 2
1:–1
7
1 5
4 3 2
此时,的父节点不能再往下减少,因此,已经取到最大值,开始调换a[1]与a[N]的位置,
2
1 5
4 3 7
–N,变为N=5
2
1 5
4 3
对该堆继续使用之前的办法,进行最大值提取,序号为5,5/2=2,也就是从数据为1的父节点开始排
1:–2
2
4 5
1 3
2:–1
5
4 2
1 3
此时,的父节点不能再往下减少,因此,已经取到最大值,开始调换a[1]与a[N]的位置,
3
4 2
1 5
–N,变为N=4
3
4 2
1
对该堆继续使用之前的办法,进行最大值提取,序号为4,4/2=2,也就是从数据为4的父节点开始排
4:–2
3
4 2
1
3:–1
4
3 2
1
此时,的父节点不能再往下减少,因此,已经取到最大值,开始调换a[1]与a[N]的位置,
1
3 2
4
–N,变为N=3
1
3 2
对该堆继续使用之前的办法,进行最大值提取,序号为3,3/2=1,也就是从数据为1的父节点开始排
1:–1
3
1 2
此时,的父节点不能再往下减少,因此,已经取到最大值,开始调换a[1]与a[N]的位置,
2
1 3
–N,变为N=2
2
1
对该堆继续使用之前的办法,进行最大值提取,序号为2,2/2=1,也就是从数据为2的父节点开始排
2:–1
2
1
此时,的父节点不能再往下减少,因此,已经取到最大值,开始调换a[1]与a[N]的位置,
1
2
–N,变为N=1
对该堆继续使用之前的办法,进行最大值提取,序号为1,1/2=0,也就是该数据已为最小的数,无需再进行,循环解除。
至此,数组中数据从
4 7 1 3 9 2 5 8
依次寻找到,9 8 7 6 5 4 3 2 1完成堆排序。

相关代码明天补发

  • 28
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值