堆排序:首先建一个堆,然后调整堆,调整过程是将节点和子节点进行比较,将 其中最大的值变为父节点,递归调整调整次数lgn,最后将根节点和尾节点交换再n次 调整O(nlgn).
leftchild = parent * 2 + 1;
rightchild = parent * 2 + 2;
创建最大堆或者最小堆(我是最小堆)
调整堆
交换首尾节点(为了维持一个完全二叉树才要进行收尾交换)
时间复杂度:O(nlogn)
空间复杂度:O(n)
堆的结构可以分为大根堆和小根堆,是一个完全二叉树,而堆排序是根据堆的这种数据结构设计的一种排序。
每个结点的值都大于其左孩子和右孩子结点的值,称之为大根堆;每个结点的值都小于其左孩子和右孩子结点的值,称之为小根堆。
大根堆:arr(i)>arr(2i+1) && arr(i)>arr(2i+2)
小根堆:arr(i)<arr(2i+1) && arr(i)<arr(2i+2)
基本思想:
1.首先将待排序的数组构造成一个大根堆,此时,整个数组的最大值就是堆结构的顶端
2.将顶端的数与末尾的数交换,此时,末尾的数为最大值,剩余待排序数组个数为n-1
3.将剩余的n-1个数再构造成大根堆,再将顶端数与n-1位置的数交换,如此反复执行,便能得到有序数组
go
func HeapSort(arr []int) {
arrLen := len(arr)
for i := (arrLen-2)/2; i >= 0; i-- {
arrJustDown(arr, i, arrLen)
}
end := arrLen - 1
for end != 0 {
arr[0], arr[end] = arr[end], arr[0]
arrJustDown(arr, 0, end)
end--
}
fmt.Println(arr)
}
func arrJustDown(arr []int, root, n int) {
parent := root
child := parent * 2 + 1
for child < n {
if child + 1 < n && arr[child + 1] > arr[child] {
child++
}
if arr[child] > arr[parent] {
arr[child], arr[parent] = arr[parent], arr[child]
parent = child
child = parent * 2 + 1
} else {
break
}
}
}```