堆实际上是一棵完全二叉树,其任何一非叶节点满足性质:
Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]或者Key[i]>=Key[2i+1]&&key>=key[2i+2]
即任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字。
堆分为大顶堆和小顶堆,满足Key[i]>=Key[2i+1]&&key>=key[2i+2]称为大顶堆,满足 Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]称为小顶堆。由上述性质可知大顶堆的堆顶的关键字肯定是所有关键字中最大的,小顶堆的堆顶的关键字是所有关键字中最小的.
小顶堆
核心代码:
func heapSort(arr:inout [Int]) {
buildMinHeap(arr: &arr) //建立堆,无序
for i in (1..<arr.count).reversed() {
swap(&arr[i], &arr[0]) // 第一个元素和第i个元素交换
minHeap(arr: &arr, count: i, index: 0) // 第一个元素不断的调整位置
}
}
func buildMinHeap(arr:inout [Int]) {
let count:Int = arr.count
let index:Int = count/2 - 1
for i in (0...index).reversed() {
minHeap(arr: &arr, count: count-1, index: i)
}
}
func minHeap(arr:inout [Int],count:Int,index:Int) {
var parent:Int = index
var child:Int = 2*parent + 1 // 获取左子树节点
while child < count {
let right:Int = child + 1
// 如果右节点大于左节点,则选择右孩子节点
if right < count && arr[child] < arr[right] {
child += 1
}
// 如果父节点大于左右节点中的大值返回
if arr[parent] > arr[child] {
break;
}
if index != child {
swap(&arr[parent], &arr[child]) // 父节点下沉
}
parent = child // 选择孩子节点作为根节点
child = child + 1
}
}
大顶堆
核心代码:
func heapMaxSort(arr:inout [Int]) {
buildMaxHeap(arr: &arr) //建立最大堆,无序
for i in (1..<arr.count).reversed() {
swap(&arr[i], &arr[0]) // 第一个元素和第i个元素交换
maxHeap(arr: &arr, count: i, index: 0) // 第一个元素不断的调整位置
}
}
func buildMaxHeap(arr:inout [Int]) {
let count:Int = arr.count
let index:Int = count/2 - 1
for i in (0...index).reversed() {
maxHeap(arr: &arr, count: count-1, index: i)
}
}
func maxHeap(arr:inout [Int],count:Int,index:Int) {
var parent:Int = index
var child:Int = 2*parent + 1 // 获取左子树节点
while child < count {
let right:Int = child + 1
// 如果右节点小于左节点,则选择右孩子节点
if right < count && arr[child] > arr[right] {
child += 1
}
// 如果父节点小于左右节点中的大值返回
if arr[parent] < arr[child] {
break;
}
if index != child {
swap(&arr[parent], &arr[child]) // 父节点下沉
}
parent = child // 选择孩子节点作为根节点
child = child + 1
}
}
测试代码:
var minHeapData:[Int] = [16,7,3,20,17,8]
let heapSort:HeapSort = HeapSort()
heapSort.heapSort(arr: &minHeapData)
print("FlyElephant--小根堆结果---\(minHeapData)")
var maxHeapData:[Int] = [16,7,3,20,17,8]
heapSort.heapMaxSort(arr: &maxHeapData)
print("FlyElephant--大根堆结果---\(maxHeapData)")