堆排序
堆是一种叫做完全二叉树的数据结构,可以分为大根堆,小根堆,而堆排序就是基于这种结构而产生的一种程序算法。
- 大根堆:每个节点的值都大于或者等于他的左右孩子节点的值
- 小根堆:每个结点的值都小于或等于其左孩子和右孩子结点的值
排序思想
1.首先将待排序的数组构造成一个大根堆,此时,整个数组的最大值就是堆结构的顶端
2.将顶端的数与末尾的数交换,此时,末尾的数为最大值,剩余待排序数组个数为n-1
3.将剩余的n-1个数再构造成大根堆,再将顶端数与n-1位置的数交换,如此反复执行,便能得到有序数组
注意:升序用大根堆,降序就用小根堆(默认为升序)
基本实现
Golang版
func buildMaxHeap(data []int, l int) {
for i := l / 2; i >= 0; i-- {
heapAdjust(data, i, l)
}
}
func heapAdjust(data []int, start, end int) {
tmp := data[start]
for i := 2*start + 1; i <= end; i = i*2 + 1 {
if i < end && data[i] < data[i+1] {
i++
}
if data[i] > tmp {
data[start] = data[i]
start = i
} else {
break
}
}
data[start] = tmp
}
func heapSort(data []int) {
l := len(data) - 1
buildMaxHeap(data, l)
fmt.Println(data)
for i := l; i >= 0; i-- {
// Move the top of the heap to the tail of the heap in turn
data[0], data[i] = data[i], data[0]
heapAdjust(data, 0, i-1)
}
}
Rust版
pub fn main() {
let mut data = [1, 4, 5, 7, 4, 6, 3];
heap_sort(&mut data);
println!("{:?}", data);
}
fn build_max_heap(data: &mut [i32], l: usize){
for i in (0..l/2+1).rev() {
println!("{}", i);
heap_adjust(data, i, l);
}
}
fn heap_adjust(data: &mut [i32], start: usize, end: usize){
let mut largest = start;
let left = 2 * start + 1;
let right = 2 * start + 2;
if left < end && data[left] > data[largest] {
largest = left;
}
if right < end && data[right] > data[largest] {
largest = right;
}
if largest != start {
data.swap(start, largest);
heap_adjust(data, largest, end);
}
}
fn heap_sort(data: &mut [i32]) {
let l = data.len();
build_max_heap(data, l);
for i in (1..l).rev() {
data.swap(0, i);
heap_adjust(&mut data[..i], 0, i-1);
}
}
算法分析
稳定性:
时间复杂度:
空间复杂度:
参考文献
https://blog.csdn.net/weixin_51609435/article/details/122982075