版权声明:文章为作者原创,若要转载请获得作者同意。尊重版权,从你我做起! https://blog.csdn.net/qq_37768971/article/details/88777779
一、排序方法:
堆排序
二、基本原理
1.实质:堆排序实质上最重要的在于实现一个堆,而不是设计排序的方法。
2.本篇文章采用最大二叉堆的形式完成排序(当然你也可以设计一个最小堆)。
实现二叉堆最为经典的方法,是使用数组构建一颗满二叉树,二叉树的父亲节点总是比他的子节点要来得大(注意:第二层不一定比第三层的元素要大,比如图中第7和第9节点)
3.实现二叉堆的核心在于shiftDown(下移)和shiftUp(上浮)函数,在代码中会重点标注。
三、实现代码:
package IMUHERO;
import java.util.*;
// 不使用一个额外的最大堆, 直接在原数组上进行原地的堆排序
public class HeapSort {
// 我们的算法类不允许产生任何实例
private HeapSort(){}
public static void sort(Comparable[] arr){
int n = arr.length;
// 注意,此时我们的堆是从0开始索引的
// 从(最后一个元素的索引-1)/2开始
// 最后一个元素的索引 = n-1
for( int i = (n-1-1)/2 ; i >= 0 ; i -- )
shiftDown2(arr, n, i);
for( int i = n-1; i > 0 ; i-- ){
swap( arr, 0, i);
shiftDown2(arr, i, 0);
}
}
// 交换堆中索引为i和j的两个元素
private static void swap(Object[] arr, int i, int j){
Object t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
// 原始的shiftDown过程
private static void shiftDown(Comparable[] arr, int n, int k){
while( 2*k+1 < n ){
int j = 2*k+1;
if( j+1 < n && arr[j+1].compareTo(arr[j]) > 0 )
j += 1;
if( arr[k].compareTo(arr[j]) >= 0 )break;
swap( arr, k, j);
k = j;
}
}
// 优化的shiftDown过程, 使用赋值的方式取代不断的swap,
// 该优化思想和我们之前对插入排序进行优化的思路是一致的
private static void shiftDown2(Comparable[] arr, int n, int k){
Comparable e = arr[k];
while( 2*k+1 < n ){
int j = 2*k+1;
if( j+1 < n && arr[j+1].compareTo(arr[j]) > 0 )
j += 1;
if( e.compareTo(arr[j]) >= 0 )
break;
arr[k] = arr[j];
k = j;
}
arr[k] = e;
}
// 测试 HeapSort
public static void main(String[] args) {
int N = 1000000;
Integer[] arr = SortTestHelper.generateRandomArray(N, 0, 100000);
SortTestHelper.testSort("bobo.algo.HeapSort", arr);
return;
}
}
注:关于排序的所有代码都放在我的Github上,有需要的同学可以自行Fork,如果觉得还不错,可以打个☆Star哦~~~