建立大根堆,然后修改最大最小位置,重建大根堆
构造堆
在构造有序堆时,我们开始只需要扫描一半的元素(n/2-1 ~ 0)即可,为什么?
因为(n/2-1)~0的节点才有子节点,如图1,n=8,(n/2-1) = 3 即3 2 1 0这个四个节点才有子节点
![](https://i-blog.csdnimg.cn/blog_migrate/d5fc652708d4de7bd9231adb568a969d.png)
(图1:初始状态)
所以代码4~6行for循环的作用就是将3 2 1 0这四个节点从下到上,从右到左的与它自己的子节点比较并调整最终形成大顶堆,过程如下:
第一次for循环将节点3和它的子节点7 8的元素
进行比较,最大者作为父节点(即元素60作为父节点)
【红色表示交换后的状态】
![](https://i-blog.csdnimg.cn/blog_migrate/58241227f80166435c2c05d7f2f775e6.png)
第二次
for循环将节点2和它的子节点5 6的元素进行比较,最大者为父节点(元素80作为父节点)
![](https://i-blog.csdnimg.cn/blog_migrate/40e110c64ec1d75f8543b893e900eb1c.png)
第三次
for循环将节点1和它的子节点3 4的元素进行比较,最大者为父节点(元素70作为父节点)
![](https://i-blog.csdnimg.cn/blog_migrate/12518be90d55b686a8f7250595ac9138.png)
第四次
for循环将节点0和它的子节点1 2的元素进行比较,最大者为父节点(元素80作为父节点)
![](https://i-blog.csdnimg.cn/blog_migrate/befa6fc793296f3746242dd9168c521e.png)
(注意这里,元素20和元素80交换后,20所在的节点还有子节点,所以还要再和它的子节点5 6的元素进行比较,
这就是28行代码 i = j 的原因)
至此有序堆已经构造好了!如下图:
![](https://i-blog.csdnimg.cn/blog_migrate/8607a7e555a4f45050cf958ff3ddcd0e.png)
调整堆
下面进行while循环
(1)堆顶元素80和尾40交换后-->调整堆
![](https://i-blog.csdnimg.cn/blog_migrate/cd4812a76790370e17ddf92b907b0d44.png)
(2)堆顶元素70和尾30交换后-->调整堆
![](https://i-blog.csdnimg.cn/blog_migrate/ea30e39414b78ead4be09522403e8d54.png)
(3)堆顶元素60尾元素20交换后-->调整堆
![](https://i-blog.csdnimg.cn/blog_migrate/237c5a40d083cf1af2504aedf40fafc2.png)
(4)其他依次类推,最终已排好序的元素如下: