package myapp.kit.quickstart.utils;
import java.util.Arrays;
/**
* @author huangdingsheng
* @version 1.0, 2020/6/15
*/
public class HeapSort {
public static void sort(int[] arr) {
int len = arr.length;
int startIdx = len / 2 - 1;
// init max heap
for (int i = startIdx; i >= 0; i--) {
maxHeapify(arr, i, len);
}
// sort
for (int i = len - 1; i > 0; i--) {
swap(arr, 0, i);
maxHeapify(arr, 0, i);
}
}
// heapify by idx
private static void maxHeapify(int[] arr, int idx, int heapSize) {
int l = getLeftChildIdx(idx);
int r = getRightChildIdx(idx);
if (l > heapSize - 1) {
return;
}
int largest = l;
if (r <= heapSize - 1 && arr[r] > arr[l]) {
largest = r;
}
if (arr[idx] < arr[largest]) {
swap(arr, idx, largest);
maxHeapify(arr, largest, heapSize);
}
}
// exchange x、y
private static void swap(int[] arr, int x, int y) {
int temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
// get left child index
private static int getLeftChildIdx(int idx) {
return idx * 2 + 1;
}
// get right child idx
private static int getRightChildIdx(int idx) {
return getLeftChildIdx(idx) + 1;
}
/**
* test case
*
* 输出:
* [0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9]
*/
public static void main(String[] args) {
int[] arr = new int[] {3, 5, 3, 0, 8, 6, 1, 5, 8, 6, 2, 4, 9, 4, 7, 0, 1, 8, 9, 7, 3, 1, 2, 5, 9, 7, 4, 0, 2, 6};
sort(arr);
System.out.println(Arrays.toString(arr));
}
}
maxHeapify堆调整的时间复杂度分析:
堆调整过程:
1.当前节点与子节点比较、交换(常数级别操作,设为 k)
2.递归对子节点调整
设 x 为该层节点到叶子节点的距离,则调整该节点的时间复杂度为:
T(x) = T(x - 1) + k; ( 0 < x <= lg2n)
即等差数列,其通项公式为:
T(x) = k + (x - 1) * k;
即 n 个节点的树高 lg2n
所以有 T(x) ~ kx ~ klg2n ~ lgn
因此,堆调整的时间复杂度为 O(lgn)