import java.util.Arrays;
public class Heapsort{
/**
* 表示堆里的所有元素个数
*/
private int heapLength;
/**
* 表示堆里未排序的个数
*/
private int heapSize;
/**
* 堆所在的数组
*/
private int[] arr;
public Heapsort(int[] arr){
this.arr = arr;
this.heapSize = arr.length;
this.heapLength = arr.length;
}
/**
* 获取下标为i的节点的父节点坐标
* @param i 下标为i的节点
* @return 下标为i的节点的父节点坐标
*/
private int parent(int i){
return (i+1) / 2 - 1;
}
/**
* 获取下标为i的节点的左孩子的节点的坐标
* @param i 下标为i的节点
* @return 下标为i的节点的左孩子的节点的坐标
*/
private int left(int i){
return 2*(i+1) - 1;
}
/**
* 获取下标为i的节点的右孩子的节点的坐标
* @param i 下标为i的节点
* @return 下标为i的节点的右孩子的节点的坐标
*/
private int right(int i){
return 2*(i+1);
}
/**
* 维护坐标为i的根节点的最大堆,即让坐标为i的节点的值大于其左右孩子节点的值。
* @param i 坐标为i的根节点
*/
private void maxHeapify(int i) {
int l = this.left(i);
int r = this.right(i);
int largest = i;
if(l < this.heapSize && this.arr[l] > this.arr[largest])
largest = l;
if(r < this.heapSize && this.arr[r] > this.arr[largest])
largest = r;
if(largest != i){
swap(largest, i);
this.maxHeapify(largest);
}
}
/**
* 根据数组构建最大堆,即所有的父节点的值大于等于其字节点的值。
*/
private void buildMaxHeap(){
for(int i = (this.heapLength / 2) - 1; i >= 0; i--)
this.maxHeapify(i);
}
/**
* 对arr进行堆排序。
* @原理 假设数组有n个元素。首先把数组的所有元素堆排列成一个最大堆的形式。
* 此时,最大的元素为第一个元素。然后,把数组的第一个元素与最后一个
* 元素交换。以此类推。
*/
public void heapsort(){
this.buildMaxHeap();
for(int i = this.arr.length - 1; i > 0; i--){
this.swap(0, i);
this.heapSize--;
this.maxHeapify(0);
}
}
@Override
public String toString() {
return Arrays.toString(this.arr);
}
/**
* 交换数组两个元素的位置
* @param a
* @param b
*/
private void swap(int a, int b){
arr[b] = arr[a] ^ arr[b];
arr[a] = arr[b] ^ arr[a];
arr[b] = arr[b] ^ arr[a];
}
public static void main(String[] args) {
// 示例
int[] arr = {
1, 8, 7, 2, 9, 5, 12, 5, 9};
Heapsort heapsort = new Heapsort(arr);
heapsort.heapsort();
System.out.println(heapsort);
}
}
运行结果: