什么是堆排序算法
利用堆数据结构进行排序(从小到大)
- 给定一个数组,将数组元素直接复制进堆数组中
- 然后对数据进行下沉操作,使得堆数据有序
- 将第一个元素和最后一个元素交换,此时第一个元素是小的,最后一个元素是最大的,表明最后大的元素归位,然后在除开最后一个元素的堆内对第一个元素进行进行下沉,以此类推,直到所有的元素归位
Java代码
/**
*堆排序算法
*/
package mypackage;
import java.util.Arrays;
class Heapsort{
//比较数组元素的大小
public static boolean less(Comparable[] heap, int i, int j){
return heap[i].compareTo(heap[j])<0;
}
//交换值
public static void exchang(Comparable[] heap, int i, int j){
Comparable temp=heap[i];
heap[i]=heap[j];
heap[j]=temp;
}
//根据原数组创建堆,先整体复制,然后再使用sink使得堆有序,怎么有序呢?那就是根根节点最大,且大于左右子节点,但是左右字节点大小没有要求
// 注意堆数组的元素是从索引1开始的
public static void creatheap(Comparable[] souce, Comparable[] heap){
System.arraycopy(souce,0,heap,1,souce.length);
// 从heap.length/2索引开始,对小于这个索引的元素进行下沉算法,
// 为什么呢,因为heap.length/2之前的元素是非叶子节点,heap.length/2之后的元素是叶子节点
// 叶子节点就是没有子节点的节点,不需要再下沉调整啦,
// 关键是要理解为什么heap.length/2之前的元素是非叶子节点,heap.length/2之后的元素是叶子节点
for (int i = heap.length/2; i>0 ; i--) {
sink(heap,i,heap.length-1);
}
}
// 下沉算法
// target表示对那个索引的元素进行下沉
// range表示最大索引值
public static void sink(Comparable[] heap, int target, int range) {
// while(target还有子节点的情况下)
// 如果有有右子节点,比较左右子节点,取为较大值,如果没有右子节点,将左子节点作为较大值
// 将较大值与taget索引处的值交换,这就是下沉
while (2*target<=range){
int max;
if (2*target+1<=range){
if (less(heap,2*target,2*target+1)){
max=2*target+1;
}else {
max=2*target;
}
}else {
max=2*target;
}
if (!less(heap,target,max)) {
break;
}else {
exchang(heap, target, max);
target = max;
}
}
}
// 排序算法,对元数组排序
public static void sort(Comparable[] source){
// 先创建堆,注意大小为source.length+1,因为第一个元素从索引1开始
Comparable[] heap =new Comparable[source.length+1];
creatheap(source,heap);
// 起始最大索引
int N=heap.length-1;
// while(最大索引不等于1)
// 先交换第一个元素和最后一个元素,也就是将最大元素放到最后去,这元素就算归位了,此时堆是无序的。
// 然后N--,也就是最大索引-1了,然后下沉算法就排除最大元素了,下沉算法之后,堆变为有序,且第二大的元素在根节点处
// 第二次循环,将第二大的元素在倒数第二个位置,这个元素也归位了,然后再N--,sink
// 反复执行后,元素就从先到大排序了
while (N!=1){
exchang(heap,1,N);
N--;
sink(heap,1,N);
}
// 最后复制回元数组
System.arraycopy(heap,1,source,0,source.length);
}
}
//测试
public class MyJava {
public static void main(String[] args) {
Integer[] arr={9,8,7,6,5,4,3,2,1};
Heapsort.sort(arr);
System.out.println(Arrays.toString(arr));
}
}
结果正确