排序算法-堆排序
堆是一个完全二叉树
堆排序是指利用堆这种数据结构所设计的一种排序算法
大顶堆:每个结点的值都大于或等于其左右孩子结点的值
arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]
小顶堆:每个结点的值都小于或等于其左右孩子结点的值
arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]
堆排序的基本思想是:将待排序序列构造成一个大顶堆(小顶堆同理),此时,整个序列的最大值就是堆顶的根节点。 将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得 到n个元素的次小值。如此反复执行,便能得到一个有序序列了。
堆排序的过程
1.将给定无序队列构成一个二叉堆(一般升序排序会将这个二叉堆调整成大顶堆,降序队列调整成小顶堆)
arr=4 6 8 5 9
2.从最后一个非叶子节点开始从左至右调整,上面的5,9,8都是叶子节点,所以从6开始
最后一个非叶子节点index=arr.length/2-1=5/2-1=1
arr[1]=6
把arr[1]和它的左右儿子(arr[12+1],arr[12+2])比较,把最大的调整到arr[1]的位置上
3.找到倒数第二个非叶子节点4,和它的左右子节点比较交换
4.交换指挥456顺序不正确继续调整
这是这已经是一个大顶堆了
5、将堆顶元素与末尾元素进行交换(交换后不参与重建),使末尾元素最大。然后继续调整堆,再次变成大顶堆后将堆顶元素与末尾元素交换,得到第二大元素。如此反复进行交换,重建。
6.反复交换重建
代码实现
public class HeapSort {
public static void main(String[] args) {
int[] arr = {
1,7, 6, 4, 3, 5, 2, 10, 9, 8};
System.out.println("排序前:" + Arrays.toString(arr));
sort(arr);
System.out.println("排序后:" + Arrays.toString(arr));
}
public static void sort(int[] array) {
// 1. 把无序数组构建成最大堆,从最后 非叶子节点开始
for (int i = array.length / 2 - 1; i >= 0; i--) {
adjustHeap(array, i, array.length);
}
// 2. 调整堆结构+交换堆顶元素与末尾元素,调整堆产生新的堆顶
for (int i = array.length - 1; i > 0; i--) {
// 最后1个元素和第1个元素进行交换
int temp = array[i];
array[i] = array[0];
array[0] = temp;
// “下沉”调整最大堆
adjustHeap(array, 0, i);
}
}
public static void adjustHeap(int[] array, int parentIndex, int length) {
// temp 保存父节点值,用于最后的赋值
int temp = array[parentIndex];
int childIndex = 2 * parentIndex + 1;
while (childIndex < length) {
// 如果有右孩子,且右孩子大于左孩子的值,则定位到右孩子
if (childIndex + 1 < length && array[childIndex + 1] >array[childIndex]) {
childIndex++;
}
// 如果父节点大于任何一个孩子的值,则直接跳出
if (temp >= array[childIndex]) {
break;
}
//无须真正交换,单向赋值即可
array[parentIndex] = array[childIndex];
parentIndex = childIndex;
//下一个左孩子
childIndex = 2 * childIndex + 1;
}
array[parentIndex] = temp;
}
}
还没有评论,来说两句吧...