堆排学习笔记

原理:

设有n个数字,初始状态n个数字随机排序,最终实现从大到小的顺序

堆排的本质是构成一个二叉树,其二叉树的特性是子树都比其父亲的数值要小(针对从大到小的排序而言,这种树叫最大堆)

堆排序一共分成三步

1.构建初始二叉树,将本无序的堆栈,以最大堆的形式重新构造,以便于接下来的步骤的进行

2.将最大的数字(位于树的根部)和最底端的数字交换(换到数组最后面),再将最底端被交换的那个数字(此时已经被换到了树的根部)沉没下去,使二叉树再次变成一个最大堆(不算被交换到数组底部的那个数字),接着再次重复此步骤

3.完成所有步骤之后,按顺序打印,即可获得一个从大到小的序列

图示:

图源:https://blog.csdn.net/sxhelijian/article/details/50295637

第一步:构造的过程:从最后一个节点开始遍历,每次走到一个节点时:比较它的父亲,兄弟,以及它自己三者大小,并且将最大的移到父亲的位置

构造结束后,堆中的情况:

 

第二步:交换的过程

 

 

 第三步:打印的过程,不再赘述

代码:

明白思路过后,就要搞出一份代码来,下面是我的各个步骤的代码,每个人的代码风格格式均不相同,仅供参考

 下沉过程:down

 1 void down(int x)//把小的元素下沉 x是数字在数组中的位置 n代表数组中未完成排序的数的总量 
 2 {
 3     while((x*2<=n&&number[x]<number[x*2])||(x*2+1<=n&&number[x]<number[x*2+1]))//当该节点的数比它的儿子小时 
 4     {
 5         if(number[x*2]<number[x*2+1]&&x*2+1<=n)//如果比右儿子比左儿子大,交换该节点和它的右儿子 
 6         {
 7             swap(number[x],number[x*2+1]);
 8             x=x*2+1;
 9         }
10         else if(number[x*2+1]<=number[x*2])//如果左儿子比右儿子大,交换该节点和它的左儿子 
11         {
12             swap(number[x],number[x*2]);
13             x=x*2;
14         }
15         else if(number[x*2+1]>number[x*2]&&x*2+1>n)//特殊情况,右儿子大于左儿子,但是右儿子是已经排序完的数字,不可以交换 
16         {
17             break;
18         }
19     }
20 }

上浮过程:up

1 void up(int x)//把大的元素上浮
2 {
3     while(number[x]>number[x/2]&&x>1)//如果该节点大于它的父亲节点,那么将它和它的父亲节点交换
4     //这里务必要注意x>1的条件,不然会遍历到number[0],我没有在number[0]中放数字所以我加了这个条件 
5     {
6         swap(number[x],number[x/2]);
7         x=x/2;//继续循环直到这个节点不再大于它的父亲节点 
8     }
9 }

在数组尾端插入新数:Insert

1 void Insert(int newNumber)//插入新的数字进入堆中 
2 {
3     n++;//堆中数字总数增加 
4     number[n]=newNumber;
5     up(n);//把新加入的数字上浮,确保堆不被破坏仍然是一个最大堆 
6  }

主函数:

因为使用堆的情况不同,这里我就不放我的主函数了,简要说明一下堆排主函数大致的实现方法

1.将每个数字用Insert函数插入到数组中,使其一直保持为一个最大堆(或最小堆)

2.将根节点和数组最后的节点交换,并将n减少1,此后的操作不再改变该数字在数组中的位置

3.将被转移到现在的根节点的位置的数,沉没下去,以便该堆仍为一个最大堆,也保证了沉没后的堆的根节点是最大值(除了被处理完的数以外最大)

4.重复2.3两步直到n==1为止

5.此时的数组就是一个从小到大顺序排列好的数组


 

以上就是堆排的主要操作的过程,其中,下沉过程中的if 判断很值得思考,我在第一次使用堆排的时候发生了很严重的错误,因为没有考虑全if的条件导致最后发生死循环。

如果您也是一位初学者,我非常建议您在理解堆排的过程中不仅要自己敲一遍代码,还应该画出堆中节点的swap过程,这样有助于理解和记忆。

希望我的这篇学习笔记对您的学习有所帮助。

 

posted @ 2020-10-28 20:02  _厨师沙拉  阅读(134)  评论(0)    收藏  举报