堆是一种完全二叉树,可以用数组的形式表示,如下表所示
左孩子 | 右孩子 | 父节点 | |
节点i | i * 2 + 1 | i * 2 + 1 + 1 | (i - 1) / 2 |
给定一个数组,构造堆(以大根堆——(父节点>子节点,根节点为最大值)为例)
对于数组中的每一个元素,比较其与其父节点的大小;若该元素比父节点大,则交换该元素与其父节点位置,直到该元素为根节点或该元素不大于其父节点为止。
heapify:假定数组中有一个值发生变化,如何重新调整数组成为大根堆
找到变化值 i 的左右两个孩子(如果存在),找到左右两个孩子间的最大值,若最大值比 i 大,则交换 i 与最大值,直到 i 不小于它的左右两个孩子。
给定数组,进行堆排序:
1、构建大根堆(或小根堆,以大根堆为例)
2、把大根堆的根节点与数组最后一个元素交换,对于数组中前n-1项(数组共有n项)heapify。
/**
* @yjw 2018/07/10
*/
public class HeapSort {
public void heapSort(int[] arr){
for(int i = 0; i < arr.length; i++){
heapInsert(arr, i);
}
int size = arr.length;
while(size > 0){
heapify(arr, 0, size);
swap(arr, 0, --size);
}
}
public static void heapInsert(int[] arr, int index){
while(arr[index] > arr[index-1]/2){
swap(arr, index, (index-1)/2);
index = (index-1)/2;
}
}
public static void heapify(int[] arr, int index, int size){
int left = index * 2 +1;
while(left < size){
int largest = left + 1 < size && arr[left+1] > arr[left] ? left + 1 : left;
largest = arr[largest] > arr[index] ? largest : index;
if(largest == index){
break;
}
swap(arr, largest, index);
index = largest;
left = index * 2 +1;
}
}
public static void swap(int[] arr, int i, int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}