1.堆排序的Java实现:
代码如下:
package com.zm.testSort;
/**
* 堆排序
* @author zm
*/
public class HeapSort {
public static void getHeapSort(int[] a) {//堆排序
int n = a.length;
if(a == null || n == 1) {
return;
}
buildMaxHeap(a, n);//调用构建最大堆方法,构建一个最大堆
swap(a, 0, n-1);//交换堆顶元素和堆尾元素,将最大元素置于数组尾端
for(int len = n-1; len > 1; len--) {//此时需比较的数组长度为n-1,由于此时除了堆顶元素之外,其他元素都符合最大堆,因此只需每次调整堆顶元素
adjustDown(a, 0, len);//0代表堆顶元素,len代表需比较的数组部分长度
swap(a, 0, len-1);//交换需比较的数组部分的堆顶元素和堆尾元素
}
}
public static void buildMaxHeap(int[] a, int length) {//构建最大堆
int k = (length -2)/2;//获取堆尾元素的父节点的索引
for(; k >=0; k--) {//由该索引开始,从右往左,从下到上,依次调整
adjustDown(a, k, length);//k表示当前(非叶子节点)父节点的索引
}
}
public static void adjustDown(int[] a, int k, int length) {//调整当前节点与它的所有子节点,构建子最大堆
int temp = a[k];
for(int i = 2*k+1; i < length; i = 2*i+1) {//i为父节点的左子节点
if((i+1)<length) {//如果有右子节点
if(a[i] < a[i+1]) {//如果右子节点比左子节点大
i++;
}
}
if(temp < a[i]) {//如果父节点小于左右子节点中的最大者
a[k] = a[i];
k = i;//移到子节点中的大着节点上
}else{
break;
}
}
a[k] = temp;
}
public static void swap(int[] a, int b, int c) {
int temp = a[b];
a[b] = a[c];
a[c] = temp;
}
public static void main(String[] args) {
int[] a = {3, 5, 1, 2, 6, 4, 7, 11, 23, 44, 3, 34, 8, 23, 6, 9};
getHeapSort(a);
System.out.print("堆排序:");
for(int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
}
}
2.堆排序的性能分析:
时间复杂度:
1. 最好情况:O(nlog2(n))
2. 平均情况:O(nlog2(n))
3. 最坏情况:O(nlog2(n))
空间复杂度:O(1)
稳定性:不稳定(相同元素的相对位置会改变)
3.适用场景
3.1:若n较大,则应采用时间复杂度为O(nlog2(n))的排序方法:快速排序、堆排序或归并排序。
快速排序是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短;
堆排序所需的辅助空间少于快速排序,并且不会出现快速排序可能出现的最坏情况。这两种排序都是不稳定的。
3.2:优先队列通常用堆排序来实现。