1. 堆排序的思想
堆具有父结点值大于子结点的特性,所以大顶堆的根结点是堆中值最大的,将根结点与最后一个结点的位置交换后,堆特性被打破;在排除最后一个位置后,再进行堆的更新,使其重新满足堆特性,之后再将新的根结点与倒数第二个位置的数据交换,如此重复直到只剩下根结点一个结点时停止。
2. 代码
import java.util.Arrays;
public class HeapSort {
public static void main(String args[]) {
int []a = new int[] {5,9,3,7,6,5};
heapSort(a);
System.out.println(Arrays.toString(a));
}
static int parent(int i) {
return (i - 1)/2;
}
static int left(int i) {
return 2*i + 1;
}
static int right(int i) {
return 2*i + 2;
}
static void maxHeapfy(int []a,int i,int heapSize) { //数组a,第i个结点,heapSize是数组种实际要排序的元素的长度
int left = left(i); //有的时候能够递归到叶子结点,叶子结点无后继,下面两个if都注意到了这一点
int right = right(i);
int largest = i;
if(left < heapSize && a[left] > a[largest]) { //
largest = left;
}
if(right < heapSize && a[right] > a[largest])
{
largest = right;
}
if(largest != i) { //把最大值给父结点
a[largest] = a[largest] ^ a[i];
a[i] = a[largest] ^ a[i];
a[largest] = a[largest] ^ a[i];
maxHeapfy(a,largest,heapSize); //发生交换之后还要保证大根堆性质
}
}
static void buildMaxHeap(int []a,int heapSize) {
for(int i = (heapSize-2)/2;i >= 0;i--) {
maxHeapfy(a,i,heapSize);
}
}
static void heapSort(int []a) {
int len = a.length;
buildMaxHeap(a,len); //初始建堆
a[len-1] = a[0] ^ a[len-1]; //交换
a[0] = a[0] ^ a[a.length-1];
a[len-1] = a[0] ^ a[len-1];
for(int i = 1;i<len-1;i++) { //初始建堆之后还要排a.length-2次
maxHeapfy(a,0,len-i);
a[len-1-i] = a[0] ^ a[len-1-i]; //交换
a[0] = a[0] ^ a[len-1-i];
a[len-1-i] = a[0] ^ a[len-1-i];
}
}
}