踏踏实实积累,不要浮躁,在学习上是糊弄不过去的!!
大根堆定义:父节点都大于等于它的子节点(递归定义下去)
堆排序思想: 本质上还是在数组上的比较和交换操作流程如下:
1:构造大根堆从下往上构造只需要扫描一半的元素因为n/2 -> n这段区间内的元素是叶子节点不会参与
2:排序,将堆顶元素跟数组中最后一个元素交换然后再进行sink()操作调整堆
package sort;
import edu.princeton.cs.algs4.StdOut;
import tools.Util;
public class heapSort {
private heapSort(){};
public static void sort(Comparable[] pq) {
int n = pq.length;
// 构造堆 只用扫描一半的元素
for (int k = n/2; k >= 1; k--){
sink(pq, k, n);
}
while (n > 1) {
exch(pq, 1, n--);
sink(pq, 1, n);
}
}
private static void sink(Comparable[] pq, int k, int n) {
while (2*k <= n) {
int j = 2*k;
if (j < n && less(pq, j, j+1)){
j++;
}
if (!less(pq, k, j)){
break;
}
exch(pq, k, j);
k = j;
}
}
private static boolean less(Comparable[] pq, int i, int j) {
return pq[i-1].compareTo(pq[j-1]) < 0;
}
private static void exch(Object[] pq, int i, int j) {
Object swap = pq[i-1];
pq[i-1] = pq[j-1];
pq[j-1] = swap;
}
public static void main(String[] args) {
String arr[] = {"a","f","d","v","w"};
heapSort.sort(arr);
Util.println(arr);
}
}
说明:
1:在堆排序中可以分成两个阶段,建堆和排序
2:建堆过程中采用从后往前也就是从下往上的策略这样只需要扫描一半的元素
3:排序过程中涉及到交换堆顶和最后一个元素的位置,导致堆排序不稳定
思考:为什么工程应用中堆排序比快速排序慢
1:堆排序的比较操作对CPU缓存不友好,他是跳着比较的
2:建堆过程打乱了数据原本的有序性