7、堆排序
堆排序与简单选择排序的区别:
简单选择排序第一次进行n-1次的比较得到最小值,然后在剩余的n-1个记录中进行n-2次比较得出次小值。事实上,可以利用前n-1次比较的信息,来减少比较的次数,从而提高效率,堆排序采用树形结构保留了比较结果,从而减少了比较次数。
堆排序的基本思想:
1)先将数组data[0,1,...,n-1]建成一个大顶堆(或者小顶堆),即原始无序区;
2)取关键字最大(或最小)的记录,即堆顶元素,与无序区的最后一个记录交换,由此得到新的无序区data[1,2,...,n-2]和有序区data[n-1];
3)对新的无序区进行调整,重新调整成大顶(或者小顶)堆;
4)如此反复操作,直至排序结束。
堆排序的特点:
堆排序是一种树形选择排序,其特点是:将数组data[0,1,...,n-1]看成是一个完全二叉树,堆的含义表明,完全二叉树中所有非终端节点的值均不大于(或不小于)其左右孩子节点的值。若数组arr是堆,则堆顶元素(或完全二叉树的根)必为序列中n个元素的最小值(或最大值)。
java实现:
public class SortAlgorithm {
//堆排序
public static void heapSort(int[] data){
System.out.println("开始排序");
int arrayLength = data.length;
//循环建堆
for(int i=0;i<arrayLength-1;i++){
//建堆
buildMaxHeap(data,arrayLength-1-i);
//交换堆顶和最后一个元素
swap(data,0,arrayLength-1-i);
System.out.println(Arrays.toString(data));
}
}
private static void swap(int[] data, int i, int j) {
int tmp=data[i];
data[i]=data[j];
data[j]=tmp;
}
//对data数组从0到lastIndex建大顶堆
private static void buildMaxHeap(int[] data, int lastIndex) {
//从lastIndex处节点(最后一个节点)的父节点开始
for(int i=(lastIndex-1)/2;i>=0;i--){
//k保存正在判断的节点
int k=i;
//如果当前k节点的子节点存在
while(k*2+1<=lastIndex){
//k节点的左子节点的索引
int biggerIndex=2*k+1;
//如果biggerIndex小于lastIndex,即biggerIndex+1代表的k节点的右子节点存在
if(biggerIndex<lastIndex){
//若右子节点的值较大
if(data[biggerIndex]<data[biggerIndex+1]){
//biggerIndex总是记录较大子节点的索引
biggerIndex++;
}
}
//如果k节点的值小于其较大的子节点的值
if(data[k]<data[biggerIndex]){
//交换他们
swap(data,k,biggerIndex);
//将biggerIndex赋予k,开始while循环的下一次循环,重新保证k节点的值大于其左右子节点的值
k=biggerIndex;
}else{
break;
}
}
}
}
public static void main(String[] args){
int[] a={49,38,65,97,76,13,27,49};
System.out.println("排序之前:\n"+Arrays.toString(a));
heapSort(a);
System.out.println("排序之后:\n"+Arrays.toString(a));
}
}
引自:http://www.cnblogs.com/sunnychuh/archive/2011/07/18/2109428.html
结果:
排序之前:
[49, 38, 65, 97, 76, 13, 27, 49]
开始排序
[38, 76, 65, 49, 49, 13, 27, 97]
[27, 49, 65, 38, 49, 13, 76, 97]
[13, 49, 27, 38, 49, 65, 76, 97]
[13, 49, 27, 38, 49, 65, 76, 97]
[13, 38, 27, 49, 49, 65, 76, 97]
[27, 13, 38, 49, 49, 65, 76, 97]
[13, 27, 38, 49, 49, 65, 76, 97]
排序之后:
[13, 27, 38, 49, 49, 65, 76, 97]
堆排序的性能:
堆排序的时间,主要由建立初始堆和反复重建堆这两部分的时间开销构成。
堆排序的最坏时间复杂度为O(nlogn);
堆序的平均性能较接近于最坏性能,相对于快速排序来说,这是堆排序最大的优点;
由于建初始堆所需的比较次数较多,所以堆排序不适宜于记录数较少的文件,但对n较大的文件还是比较有效的;
堆排序是就地排序,辅助空间为O(1);
它是不稳定的排序方法。