以大顶堆举例:
- 1、首先用构造一个初始的大顶堆
- 2、然后将堆顶和堆尾的一个元素交换,交换后的队尾元素加入排序队列尾
- 3,重新构建堆
- 4,重复步骤2-3
理解上就是每次选取堆的最大值,之后将最大值删除,重构堆再重复以上操作
- 在Java中我们常用优先队列构建大顶堆和小顶堆
PriorityQueue<Integer> pq = new PriorityQueue<>();
- 在后边的括号中使用Lamba表达式调整大顶堆和小顶堆
使用代码实现一个堆排序如下
package sort;
import java.util.Arrays;
import java.util.Scanner;
/**
* @auther alex
* @description for test
* @data 2021/3/10
**/
public class HeapSort {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int len = 4;
int[] test = new int[len];
for(int i = 0;i < len;i++){
test[i] = scanner.nextInt();
}
headSort(test);
System.out.println(Arrays.toString(test));
}
//堆排序函数
private static void headSort(int[] arr){
//创建初始堆,从第一个非叶子节点开始调整堆
for(int i = (arr.length - 1) / 2;i >= 0;i--){
adjustHeap(arr,i,arr.length);
}
//交换堆顶和堆底的元素,删除堆底最大值入排序序列
//调整堆结构
//调整堆结构+交换堆顶元素与末尾元素
for (int i = arr.length - 1; i > 0; i--) {
//将堆顶元素与末尾元素进行交换
int temp = arr[i];
arr[i] = arr[0];
arr[0] = temp;
//重新对堆进行调整
adjustHeap(arr, 0, i);
}
}
//调整堆
private static void adjustHeap(int[] arr,int parent,int length){
//将temp作为父节点
int temp = arr[parent];
//左孩子
int lChild = 2 * parent + 1;
while (lChild < length) {
//右孩子
int rChild = lChild + 1;
// 如果有右孩子结点,并且右孩子结点的值大于左孩子结点,则选取右孩子结点
if (rChild < length && arr[lChild] < arr[rChild]) {
lChild++;
}
// 如果父结点的值已经大于孩子结点的值,则直接结束
if (temp >= arr[lChild]) {
break;
}
// 把孩子结点的值赋给父结点
arr[parent] = arr[lChild];
//选取孩子结点的左孩子结点,继续向下筛选
parent = lChild;
lChild = 2 * lChild + 1;
}
arr[parent] = temp;
}
}