- 堆排序
堆排序(heapsort)是一种树形选择排序,是对直接选择排序的有效改进。
直接选择排序:数据直接进行比较置换,第一个位置保存最小值,依此类推排序。简单代码如下:
for(int i=0;i<d.length-1;i++) {
int min=d[i],tmp; //记录第i位置
for(int j=i+1;j<d.length;j++) { //与i后的所有数据比较
if(d[j]<min){tmp=d[j];d[j]=min;min=tmp;}//置换(不稳定)
d[i]=min;//得到n-i个元素中最小的元素
}
基本的思考:
堆排序是把序列看作是一棵顺序存储的二叉树(一维数组存储二叉树),调整存储序,使之成为一个堆,将堆顶元素输出,得到n 个元素中最小(或最大)的元素。依此类推。
列出问题:
①如何将n 个待排序的数建成堆;
②输出堆顶元素后,怎样调整剩余n-1 个元素,使其成为一个新堆。
int[] data = {81,94,11,96,12,35,17,95,28,58,41,75,15};
//大顶堆
public static void heapSort(int[] d) {
//建堆
for(int i=(d.length-1)/2;i>=0;i--) {
heapSortBig(d,i,d.length);
}
//输出堆顶
int tmp;
for(int i=d.length-1;i>0;i--) {
//交换堆顶元素和堆中最后一个元素
tmp =d[i];d[i]=d[0];d[0]=tmp;
//每次交换堆顶元素和堆中最后一个元素之后,重建堆
heapSortBig(d,0,i);//d[i]=11 12 15 17 ...
}
//打印排序结果(大顶堆从小到大排序)
for(int a:d) {
System.out.print(" "+a);
}
}
public static void heapSortBig(int[] array, int s, int length) {
int tmp = array[s];//堆顶
int child = 2 * s + 1;// 左孩子结点的位置
while (child < length) {
// child + 1 是当前调整结点的右孩子
// 如果有右孩子且小于左孩子,使用右孩子与结点进行比较,否则使用左孩子
if (child + 1 < length && array[child] > array[child + 1]) {
child++;
}
// 如果较小的子孩子比此结点小
if (array[s] > array[child]) {
array[s] = array[child];// 把较小的子孩子向上移动,替换当前待调整结点
s = child;// 待调整结点移动到较小子孩子原来的位置
array[child] = tmp;
child = 2 * s + 1;// 继续判断待调整结点是否需要继续调整
} else {
System.out.println("子孩子均比其大,调整结束");
break;// 当前待调整结点小于它的左右孩子,不需调整,直接退出
}
}
}
思考:
基础:第一阶段构建堆最多用到2N次比较。第二阶段比较最多是2NlogN-O(N)次了。 是个非常稳定的算法。