堆排序笔记
堆排序学习网站
一开始直接看别人写的堆排序,感觉不能理解,后来看了这个视频网站,就好理解了。
视频链接:http://www.iqiyi.com/v_19rrhzzs1k.html
堆排序的实现与笔记
做个笔记,方便以后自己回顾。
public class 第四次实现堆排序 {
public static void main(String[] args) {
int[] array = {2,4,235,23,6,3,7,34,5,7,457};
sortHeap(array);
print(array);
}
/**
* 调整堆——要实现升序的话,需要构建的是大顶堆
* @param a 数组
* @param s 父节点下标
* @param length 有效长度,即参与调整的数组部分(这里没理解好,在sortHeap方法调用该方法的时候就会出问题)
*/
public static void adjustHeap(int[] a, int s, int length){
int temp;
temp = a[s]; //当执行完这一步,下标s对应的位置就相当于一个空的位置
for(int j=2*s;j<length;j=2*j){ //因为length表示的是数组的有效长度,而j表示的是数组下标,因此要j一定要小于length
if(j<length-1 && a[j]<a[j+1]) //这里我觉得是j<length-1而不是j<length
j++; //目的是找出较大的子节点的下标
if(temp>=a[j]) //如果父节点就是比较大的子节点还大,那就无需调整了,跳出循环
break;
a[s] = a[j]; //否则就将较大的那个子节点的数据放到父节点中(最开始的父节点中的数据已经存储在temp中了),如此下标j指向的位置就成了空位置
s = j; //让下标s指向新的空位置
}
a[s] = temp; //最后把temp中存储的父节点元素存到空位置上
}
public static void sortHeap(int[] a){
/*
* 理解好,堆在逻辑结构上是一颗完全二叉树,但是在物理结构上是用数组来表示
* 因此,没有填充堆这一操作,因为我们是用数组来表示,因此,本身就已经填充好了
* 我们要做的,是调整,使之成为一个大顶堆,然后再执行堆排序
*/
//如何调整堆,使之成为大顶堆?从逻辑结构上看,堆是一个完全二叉树,我们从最后一个非叶子节点开始调整(叶子节点无需调整),一直往前,对每个非叶子节点进行遍历,从而生成一个大顶堆
int length = a.length;
for(int i=(length-1)/2;i>=0;i--)
adjustHeap(a,i,length); //(很重要!!)根据adjustHeap方法参数的理解,最后一个参数代表有效长度,因此这里是写length而不是length-1!!!!!
//堆排序
for(int j=length-1;j>0;j--){
//把堆顶元素换到最后
swap(a,0,j);
//调整堆
adjustHeap(a,0,j); //(很重要!!)最后一个参数是j还是j-1?按照adjustHeap方法参数的理解是有效长度!!那么应该是j才对!
}
}
//交换方法
public static void swap(int[] c,int a,int b){
int temp = c[a];
c[a] = c[b];
c[b] = temp;
}
//打印方法
public static void print(int[] a){
for(int i:a)
System.out.print(i+" ");
}
}
/*
* 对堆排序的理解:
* 堆排序,就是排序算法的一种。要求是使用数组,而不能是链表。也没有说是树结构。
* 我们使用堆排序的思想就是利用完全二叉树的结构,也就是说我们建造的堆就是一个完全二叉树结构,这是逻辑上的结构,但其物理结构则是用数组来表示完全二叉树的。
*/
/*
* 堆排序适合于数据量非常大的场合(百万数据)。
* 堆排序不需要大量的递归或者多维的暂存数组。这对于数据量非常巨大的序列是合适的。
* 比如超过数百万条记录,因为快速排序,归并排序都使用递归来设计算法,在数据量非常大的时候,可能会发生堆栈溢出错误。
* 堆排序会将所有的数据建成一个堆,最大的数据在堆顶,然后将堆顶数据和序列的最后一个数据交换。
* 接下来再次重建堆,交换数据,依次下去,就可以排序所有的数据。
*/
时间复杂度
每次调整heap中k个元素重新建立堆的时间复杂度与堆的高度有关,为O(logk),又需要对n个元素进行调整,时间复杂度为O(n),因此总的时间复杂度为O(nlogk)。堆排序在最好、最差、平均情况下的时间复杂度都为O(nlogk)。
拓展链接
堆排序的应用场景:http://blog.csdn.net/shakespeare001/article/details/51360732