Java code:
package com.cn.insertion;
public class HeadSort {
public static void main(String[] args) {
int[] a = new int[]{4, 1, 3, 2, 16, 9, 10, 14, 8, 21};
HeadSort heapSort = new HeadSort();
heapSort.headSort(a);
for (int i = 0; i < a.length; i++) {
System.out.println(a[i]);
}
}
/**
* 这个是排序函数,因为大顶堆的根节点可以确定是最大的,所以每次交换
* 根节点到最后面,然后大顶堆的节点数目减一,后面的一定是排好序了的。
* 这个函数共进行O(n)趟,所以整个排序的时间复杂度为O(nlog(n)).
* @param a
*/
public void headSort(int[] a) {
buildMaxHeap(a);
int heapLength = a.length;
for (int i = 0; i < a.length - 1; i++) {
exchange(a, 1, heapLength);
heapLength--;
maxHeapify(a, 1, heapLength);
}
}
/**
* 建立一个大顶堆,大顶堆满足父节点比两个孩子节点都大
* @param a
*/
public void buildMaxHeap(int[] a) {
int heapLength = a.length;
for (int i = a.length/2; i >= 1; i--) {
maxHeapify(a, i, heapLength);
}
}
//下面三个方法分别求出父节点,左孩子,右孩子
public int parent(int i) {
return i/2;
}
public int leftChild(int i) {
return 2*i;
}
public int rigthChild(int i) {
return 2*i + 1;
}
/**
* 三个参数a是要排序的数组,m是从那一个节点开始调整,n是我们要调整的堆的总长度。
* 每次找到父节点,左孩子,右孩子三个节点中最大的那一个,如果不是父节点最大,就
* 交换父节点与这个最大值得节点(可能是左孩子,也可能是右孩子),然后与父节点交
* 换了的节点的值变动了,所以在调用这个函数对以该节点为父节点的三堆在进行一次调
* 整。这样一趟调整的时间复杂度是O(log(n))。
* @param a
* @param m
* @param n
*/
public void maxHeapify(int[] a, int m, int n) {
int l = leftChild(m);
int r = rigthChild(m);
int largest = m;
if (l <= n && a[l - 1] > a[m - 1]) {
largest = l;
}
if (r <= n && a[r - 1] > a[largest - 1]) {
largest = r;
}
if (largest != m) {
exchange(a, m, largest);
maxHeapify(a, largest, n);
}
}
//对数组中的两个元素进行交换
public void exchange(int[] a, int m, int n) {
a[m - 1] = a[m - 1] + a[n - 1];
a[n - 1] = a[m - 1] - a[n - 1];
a[m - 1] = a[m - 1] - a[n - 1];
}
}