参考博客
1.堆排序介绍
算法复杂度:O(nlogn)
堆排序:堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
堆是完全二叉树,分两类:
- 大顶堆:每个结点的值都大于或等于其左右孩子结点的值,arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]
- 小顶堆:每个结点的值都小于或等于其左右孩子结点的值arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]
同时,我们对堆中的结点按层进行编号,将这种逻辑结构映射到数组中就是下面这个样子
2. 堆排序的基本思路
堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了。
- a. 将无序序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆;
- b. 将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端;
- c. 重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。
2.1 具体步骤
给定无序序列结构如下
目标堆:
3. 代码
package com.sort;
/**
* @Author 黄军威
* @create 2019/9/2 0:39
* @email hjunwei@foxmail.com
*/
//堆排序
public class HeapSort {
private static int len;
public static void main(String [] args){
int [ ] data = {8, 3, 10, 1, 6, 14, 4, 7};
/* 实现 堆排序,使 */
heapSort(data);
}
public static int [] heapSort(int [] array){
len = array.length;
if(len<1){
return array;
}
//构建一个最大堆;
for(int i=(len-1)/2; i>=0; i--){
adjustHeap(array,i);
}
//循环将堆首位(最大值)与末位交换,然后在重新调整最大堆
while(len>1){
swap(array, 0, len-1);
len--;
adjustHeap(array, 0);
}
return array;
}
//将堆首位(最大值)与末位交换
private static void swap(int[] array, int i, int j) {
int a = array[i];
array[i] = array[j];
array[j] = a;
}
/** 调整使array成为最大堆 * */
private static void adjustHeap(int[] array, int i) {
int maxIndex = i;
//如果有左子树,且左子树大于父节点,则将最大自增指向左子树
if(i*2 < len && array[i*2] > array[maxIndex]){
maxIndex = i*2;
}
//如果有右子树,且右子树大于父节点,则将最大自增指向右子树
if(i*2+1 < len && array[i*2+1] > array[maxIndex]){
maxIndex = i*2 + 1;
}
//如果父节点不是最大值,这将父节点与最大值交换,并且递归调整与父节点交换的位置
if(maxIndex != i){
swap(array, maxIndex, i);
adjustHeap(array, maxIndex);
}
}
}
输出结果
排序前:[7, 6, 7, 11, 5, 12, 3, 0, 1]
排序后:[0, 1, 3, 5, 6, 7, 7, 11, 12]