这是我参与「第三届青训营 -后端场」笔记创作活动的第4篇笔记。基于上一篇笔记的排序算法的基础,这次将研究较为深入的排序算法--堆排序。顾名思义,不同于之前所提到的快速排序和插入排序没有使用任何其他数据结构,堆排序利用了“堆”这一种已有的数据结构。
1.什么是堆
要认识什么是堆排序,首先得知道什么是堆。堆是一种由数组实现的完全二叉树的数据结构。而其中任一结点的值必须是子树的所有结点的最大值或最小值。而对于是最大值的情况,则称此二叉树为大根堆或者最大堆。相反,若是最小值的情况则成为小根堆或者最小堆。
2.堆排序算法
(1)将原数组构造成一个大顶堆,根据大顶堆的性质,当前堆的根节点(堆顶)就是序列中最大的元素
(2)将堆顶元素和最后一个元素交换,然后将剩下的节点重新构造成一个大顶堆
(3)重复步骤2,如此反复,从第一次构建大顶堆开始,。最后,就得到一个有序的序列了。
堆排序算法堆思想有些类似于冒泡排序,都是通过一定的手段将数组中最大的元素先找出来并放在最后(最前),然后对剩余的元素重复之前步骤。
堆排序最好和最坏的情况时间复杂度都是O(nlogn),空间复杂度O(1)。就效率上来说堆排序并不是很理想。
3.go代码
func heapSort(data Interface, a, b int) {
first := a
lo := 0
hi := b - a
// Build heap with greatest element at top.
for i := (hi - 1) / 2; i >= 0; i-- {
siftDown(data, i, hi, first)
}
// Pop elements, largest first, into end of data.
for i := hi - 1; i >= 0; i-- {
data.Swap(first, first+i)
siftDown(data, lo, i, first)
}
}