堆排序
1. 堆排序的概念
堆排序是利用大根堆或者小根堆来设计的一种排序算法,一般情况下,大根堆用于升序排列,小根堆用于降序排列。堆具备以下的特点:
1)堆实际上是一个完全二叉树,它除了最下边一层之外其他层的节点都是满的,并且最下层的节点都集中在数的左侧。
完全二叉树可以用数组来表示:
// 若将数组中的第i个节点设为N[i]
//那么其左孩子节点为N[2i + 1]
//其右孩子节点为N[2i + 2]
//其父节点可以表示为N[(i - 1) / 2]
2)在这个二叉树中,如果所有的子节点的值都大于或等于其父节点的值,称为小根堆。
如果每个节点的值都小于或等于其父节点的值,即越往下层节点的值越小,称为大根堆。
2. 堆排序的具体流程
- 将需要排序的数组构建为一个大根堆
- 每次将堆顶的元素(最大),和数组的最后一个元素交换,此时最大的元素会位于数组的最后。
- 将数组的最后一个元素去掉,不计入堆中,即数组的长度减一
- 直到待排序数组的长度为0,此时所有的元素按照升序排列
3. 堆排序的代码实现(Golang)
func heapSort(arr []int) {
//先构建一个大根堆
length := len(arr)
for i := (length -1 ) / 2; i >= 0; i-- {
heapify(arr, i)
}
//开始排序,
for i := 1;i < len(arr) ; i ++ {
arr[0],arr[length - i] = arr[length - i],arr[0]
arr1 := arr[:length -i]
heapify(arr1,0)
}
}
//下沉函数
func heapify(num []int, i int) {
for ; i*2 + 1 < len(num) ; i++ {
if num[i] < num[2*i + 1] {
num[i], num[2*i + 1] = num[2*i + 1], num[i]
}
if i*2+2 < len(num) && num[i] < num[2*i+2] {
num[i], num[2*i+2] = num[2*i+2], num[i]
}
}
}
排序结果
总结
- 这里实现的时间复杂度为O(nlogn)
- 空间复杂度为O(n)