C语言堆排序(HeapSort)的思想和代码实现
经过一晚上和有一早上的思考和学习,在Clion上反复的单步调试之后,我总结了关于堆排序这个算法的一点体会。现在来记录一下,如有错误,欢迎批评指出,谢谢!
首先:什么是堆排序,为什么叫堆?
Heapsort是一种根据选择排序的思想,利用堆这种数据结构 所设计的一种排序算法
选择排序的思想是什么?:每一趟比较找到这个序列中的最值,拿出来和最前面的元素交换,交换完之后,这个序列从前面开始减去一个(因为前面放的是最值,不需要放在序列里再次比较)
那么这里的堆是什么意思呢?:堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
什么是完全二叉树?即,每个节点都一一有序对应的满二叉树,如下图所示
当一个序列满足 双亲位置的值 大于或者小于 孩子位置的值的时候,就满足堆的关系,(这里为什么要叫做位置?因为一般都是在序列里面排序,储存是线性的,比大根堆和小根堆如顺序表)
#堆的种类,大根堆和小根堆
这个好理解,就是对应上面的图来说,双亲位置的值 大于 孩子位置的值 就是大根堆
双亲位置的值 小于 孩子位置的值 就是小根堆
实现堆排序,我们需要解决什么问题?
- 怎么创建一个初始的堆?即满足 双亲位置的值 大于或者小于 孩子位置的值,我们只需要关注每一个双亲的孩子是不是大于或者小于自己孩子,而不需要去管“别人家的孩子”是不是比自己家孩子大或者小
- 有了初始的堆之后,我们怎么调整剩下的元素,这个时候就需要看看“别人家的孩子”,这样处理之后,这个二叉树就满足完全二叉树的特点,按照序列排列下来就是一个有序的序列
Part1:创建初始堆,我们要考虑什么?
既然我们不需要去管整个序列是否有序,不需要去管“别人家的孩子”怎么样,那么我们先要
找到所有双亲节点。
怎么找呢?根据完全二叉树的性质: