一:基本思想
堆排序是利用堆(一种近似完全二叉树的结构)这种数据结构设计的一种排序算法
(1)由输入的无序数组构造一个最大堆,作为初始的无序区
(2)把堆顶元素(最大值)和堆尾元素进行互换
(3)把堆的尺寸缩小1,并调用heapify(A,0)从新的堆顶元素开始进行堆调整
(4)重复步骤(2),直到堆的尺寸为1
二.概览
分类:内部比较排序
数据结构:数组
最差时间复杂度:O(nlogn)
最优时间复杂度:O(nlogn)
平均时间复杂度:O(nlogn)
所需辅助空间:O(1)
稳定性:不稳定(不稳定发生在栈顶元素与a[i]交换的时候)
比如序列:{ 9, 5, 7, 5 },堆顶元素是9,堆排序下一步将9和第二个5进行交换,得到序列 { 5, 5, 7, 9 },再进行堆调整得到{ 7, 5, 5, 9 },重复之前的操作最后得到{ 5, 5, 7, 9 }从而改变了两个5的相对次序。
三.代码实现
public class Heap {
//交换函数
public static void Swap(int A[], int i, int j)
{
int temp = A[i];
A[i] = A[j];
A[j] = temp;
}
//建堆
public static int BuildHeap(int a[]){
int heap_size = a.length;
for (int i = heap_size/2-1;i >=0;i--){
heapify(a,i,heap_size );
}
return heap_size;
}
//堆调整
public static void heapify(int a[],int i,int size){
int left_child = 2*i +1; //左孩子索引
int right_child = 2*i + 2; //右孩子索引
int max = i;
if(left_child<size && a[left_child]>a[max]){
max = left_child;
}
if(right_child<size && a[right_child]>a[max]){
max = right_child;
}
if (max != i){
Swap(a, max, i); //把当前结点和它的最大子结点进行互换
heapify(a, max, size);//递归调用,继续从当前结点向下调整(注意下是指根)
}
}
//堆排序
public static void sort(int a[]){
//建立一个大堆
int heap_size = BuildHeap(a);
while (heap_size > 1){ // 大于1表示未完成排序
//将堆顶元素与最后一个元素交换,并从堆中去掉最后一个元素
//此处的交换很可能把后面的元素的稳定性打乱,所以堆排序不是稳定的排序
Swap(a, 0, --heap_size);
//从新的堆顶元素开始向下调整,时间复杂度o(logn)
heapify(a, 0, heap_size);
}
}
}
