您的位置:首页 > 其它

排序算法之堆排序

2015-12-09 17:43 225 查看
堆排序就是在初始时把要排序的n个数的序列看作是一棵顺序存储的二叉树(一维数组存储二叉树),调整它们的存储序,使之成为一个堆,将堆顶元素输出,得到n个元素中最小(或最大)的元素,这时堆的根节点的数最小(或者最大)。然后对前面(n-1)个元素重新调整使之成为堆,输出堆顶元素,得到n个元素中次小(或次大)的元素。依此类推,直到只有两个节点的堆,并对它们作交换,最后得到有n个节点的有序序列。

实现堆排序需解决两个问题:

1. 如何将n个待排序的数建成堆;

2. 输出堆顶元素后,怎样调整剩余n-1个元素,使其成为一个新堆。

步骤1的建堆方法:对初始序列建堆的过程,就是一个反复进行筛选的过程。

1.n 个结点的完全二叉树,则最后一个结点是第n/2个结点的子树。
2.筛选从第n/2个结点为根的子树开始,该子树成为堆。
3.之后向前依次对各结点为根的子树进行筛选,使之成为堆,直到根结点。

步骤2的建堆方法
调整大顶堆的方法:

1.设有n个元素的堆,输出堆顶元素后,剩下n-1个元素。将堆底元素送入堆顶((最后一个元素与堆顶进行交换),堆被破坏,其原因仅是根结点不满足堆的性质。
2.将根结点与左、右子树中较大元素的进行交换。
3.若与左子树交换,如果左子树堆被破坏,即左子树的根结点不满足堆的性质,则重复方法 (2).
4.若与右子树交换,如果右子树堆被破坏,即右子树的根结点不满足堆的性质。则重复方法 (2).
5.继续对不满足堆性质的子树进行上述交换操作,直到叶子结点,堆被建成。
代码:

package com.creditease.menu.sort;

import java.util.Arrays;

public class HeapSort {

public static void main(String[] args) {
int[] array = { 1, 8, 5, 2, 8, 4, 9, 2, 3, 7, 0, 6 };
heapSort(array, array.length);
System.out.println(Arrays.toString(array));
}
/**
* 调整array[index]使其成为大顶堆
* @param array
* @param index
* @param length
*/
public static void heapAdjust(int[] array, int index, int length){
int temp = array[index];// 父结点的值,用来和其子结点比较大小
int child = 2*index+1;// 左子结点的位置
while(child < length){
if(child+1 < length && array[child] < array[child+1]){// 如果左子结点小于右子结点,则用较大的右子结点与其父结点进行比较
child++;
}
if(array[index] < array[child]){// 如果较大的子结点大于其父结点
array[index] = array[child];// 对他们进行交换
index = child;// 重新设置等待调整的结点的位置
child = 2*index+1;
}else{// 如果父结点大于它的左右子结点,则不需要调整,直接退出
break;
}
array[index] = temp;// 当前等待调整的结点放到比其大的孩子结点位置上
}
}
/**
* 初始堆进行调整
* @param array
*/
public static void heapBuild(int[] array){
for(int i = (array.length-1)/2; i >= 0;i--){// 最后一个有子结点的位置
heapAdjust(array, i, array.length);
}
}
/**
* 堆排序算法
* @param array
* @param length
*/
public static void heapSort(int[] array, int length){
heapBuild(array);// 初始堆
for(int i = length-1; i > 0; i--){// 交换堆顶元素与最后一个元素
int temp = array[i];
array[i] = array[0];
array[0] = temp;
heapAdjust(array, 0, i);// 重新对堆进行调整
}
}
}


时间复杂度:

时间复杂度为 T(n) <= O(n) + (n - 1)*O(log2(n)),即等于第一次构造最大堆操作 加上 后面n-1次构造堆操作 其实由于n的减小,后面的O(log2(n))中的n也会减小,所以这里用小于等于号 。最后得到的T(n)
=O(nlog2(n)).
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: