1.算法描述:首先建一个堆,然后调整堆,调整过程是将节点和子节点进行比较,将 其中最大的值变为父节点,递归调整调整次数lgn,最后将根节点和尾节点交换再n次 调整O(nlgn).
2.算法步骤
(1)创建最大堆或者最小堆(我是最小堆)
(2)调整堆
(3)交换首尾节点(为了维持一个完全二叉树才要进行收尾交换)
3.算法go代码
package sort
import "fmt"
//堆排序
func main() {
arr := []int{1, 9, 10, 30, 2, 5, 45, 8, 63, 234, 12}
fmt.Println(HeapSort(arr))
}
func HeapSortMax(arr []int, length int) []int {
// length := len(arr)
if length <= 1 {
return arr
}
depth := length/2 - 1 //二叉树深度
for i := depth; i >= 0; i-- {
topmax := i //假定最大的位置就在i的位置
leftchild := 2*i + 1
rightchild := 2*i + 2
if leftchild <= length-1 && arr[leftchild] > arr[topmax] { //防止越过界限
topmax = leftchild
}
if rightchild <= length-1 && arr[rightchild] > arr[topmax] { //防止越过界限
topmax = rightchild
}
if topmax != i {
arr[i], arr[topmax] = arr[topmax], arr[i]
}
}
return arr
}
func HeapSort(arr []int) []int {
length := len(arr)
for i := 0; i < length; i++ {
lastlen := length - i
HeapSortMax(arr, lastlen)
if i < length {
arr[0], arr[lastlen-1] = arr[lastlen-1], arr[0]
}
}
return arr
}
4.算法解释
(1)堆的认识:堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。
(2)大顶堆和小顶堆的结构图:
以上图映射到数组就是以下数组
该数组从逻辑上讲就是一个堆结构,我们用简单的公式来描述一下堆的定义就是:
大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]
小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]
(3)了解到以上知识之后来到代码解释
代码中HeapSortMax()方法的作用如以下图解
通过循环比较把最大的值返到数组的第一个元素。
下面的方法
把数组的第一个元素与最后一个元素互换值,然后把最大值以外的值再循环比较 这样就得到了一个由小到大排序的数组。
(5)部分图片来自堆结构认识https://www.cnblogs.com/chengxiao/p/6129630.html