通过上一节发现 ,堆要不就是最大堆,要不就是最小堆,不管是最大堆还是最小堆,根节点最大值或最小值
堆排序就是通过这个特点
1.构造堆;
2.得到堆顶元素,这个值就是最大值;
3.交换堆顶元素和数组中的最后一个元素,此时所有元素中的最大元素已经放到合适的位置;
4.对堆进行调整,重新让除了最后一个元素的剩余元素中的最大值放到堆顶;
5.重复2~4这个步骤,直到堆中剩一个元素为止。
import java.util.Arrays;
public class HeapSort {
//对source数组中的数据从小到大排序
public static void sort(Comparable[] source) {
//1.创建一个比原数组大1的数组
Comparable[] heap = new Comparable[source.length + 1];
//2.构造堆
createHeap(source, heap);
//3.堆排序
//3.1定义一个变量,记录heap中未排序的所有元素中最大的索引
int N = heap.length - 1;
while (N != 1) {
exch(heap, 1, N);
//N相当于指针,N-- 并没有删除heap[N],heap[N]为最大值存储在heap里
// 每次存储当前堆中最大值到heap里
N--;
sink(heap, 1, N);
}
//4.heap中的数据已经有序,拷贝到source中
System.arraycopy(heap,1,source,0,source.length);
// System.out.println(Arrays.toString(heap));
}
//根据原数组source,构造出堆heap
private static void createHeap(Comparable[] source, Comparable[] heap) {
//1.把source中的数据拷贝到heap中,从heap的1索引处开始填充
System.arraycopy(source, 0, heap, 1, source.length);
}
//判断heap堆中索引i处的元素是否小于索引j处的元素
private static boolean less(Comparable[] heap, int i, int j) {
return heap[i].compareTo(heap[j]) < 0;
}
//交换heap堆中i索引和j索引处的值
private static void exch(Comparable[] heap, int i, int j) {
Comparable tmp = heap[i];
heap[i] = heap[j];
heap[j] = tmp;
}
//在heap堆中,对target处的元素做下沉,范围是0~range
private static void sink(Comparable[] heap,int target,int range){
while (2*target<=range){
//1.找出target结点的两个子结点中的较大值
int max=2*target; //先默认是左结点
if(2*target+1<=range){
//存在右子结点
if(less(heap,2*target,2*target+1)){
max=2*target+1;
}
}
// 2.如果当前结点的值小于结点的较大值,则交换
if(less(heap,target,max)){
exch(heap,target,max);
}
//3.更新target值
target=max;
}
}
public static void main(String[] args) {
String[] arr = {"S", "O", "R", "T", "E", "X", "A", "M", "P", "L", "E"};
HeapSort.sort(arr);
System.out.println(Arrays.toString(arr));
}
}