堆排序
什么是堆排序?
1、先让整个数组都变成大(小)根堆结构
2、把堆的最大值和堆末尾的值交换,减少堆的大小。再去调整堆。
3、堆的大小减为0之后,排序完成。时间复杂度O(n*logn)
堆排序的练习题:
已知一个几乎有序的数组,请选择一个合适的排序算法针对这个数据进行排序。
几乎有序:如果吧数组排好顺序的话,每个元素移动的距离可以不超过k,并且k相对于数组来说比较小。
首先是Java版本的解法:
package com.leftGod;
import java.util.Arrays;
import java.util.PriorityQueue;
/**
*
* 已知一个几乎有序的数组,请选择一个合适的排序算法针对这个数据进行排序。
*
* @author zhao.hualuo
* Create at 2022/4/4
*/
public class JavaNearSortProblem {
public static int[] heapSort(int[] arr, int k) {
PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(k);
int[] result = new int[arr.length];
int resultIndex = 0;
for (int i = 0; i < arr.length;) {
//将数组元素保存在优先级队列里
while (priorityQueue.size() <= k) {
priorityQueue.add(arr[i++]);
}
//将堆的第一个元素弹出(最小值)
result[resultIndex++] = priorityQueue.poll();
}
//把 堆的头 一个个弹出
while (!priorityQueue.isEmpty()) {
result[resultIndex++] = priorityQueue.poll();
}
return result;
}
public static void main(String[] args) {
int[] arr = {2,1,4,3,6,5,8,7,10,9,11,12,14,13,12};
int[] result = heapSort(arr, 3);
System.out.println(Arrays.toString(result));
}
}
下面是自定义堆结构的解法:
package com.leftGod;
import java.util.Arrays;
/**
* 已知一个几乎有序的数组,请选择一个合适的排序算法针对这个数据进行排序。
*
* @author zhao.hualuo
* Create at 2022/4/4
*/
public class NearSortProblem {
/**
* 堆排序
*
* @param arr 数组
* @param k 变量
* @return 排好序的数组
*/
public static int[] heapSort(int[] arr, int k) {
//声明一个堆数组
int heapSize = 0;
int[] heapArr = new int[k];
int resultIndex = 0;
int[] result = new int[arr.length];
//遍历原数组
int arrIndex = 0;
while (arrIndex < arr.length) {
//通过heapInsert生成堆
while (heapSize < k) {
heapArr[heapSize] = arr[arrIndex];
heapInsert(heapArr, heapSize);
heapSize++;
arrIndex++;
}
//堆满了,把最小的元素拿出来
result[resultIndex++] = heapArr[0];
swap(heapArr, 0, --heapSize);
//移除最小值后,重新调整堆结构
heapify(heapArr, 0, heapSize);
}
while (heapSize > 0) {
result[resultIndex++] = heapArr[0];
swap(heapArr, 0, --heapSize);
heapify(heapArr, 0, heapSize);
}
return result;
}
private static void heapInsert(int[] arr, int index) {
while ((index-1)/2 >=0 && arr[index] < arr[(index-1)/2]) {
swap(arr, index, (index-1)/2);
index = (index-1)/2;
}
}
public static void heapify(int[] arr, int index, int heapSize) {
int leftIndex = index*2+1;
while (leftIndex < heapSize) {
int minIndex = leftIndex+1 < heapSize && arr[leftIndex+1] < arr[leftIndex] ? leftIndex+1 : leftIndex;
if (arr[minIndex] > arr[index]) {
break;
}
swap(arr, index, minIndex);
index = minIndex;
leftIndex = index*2+1;
}
}
/**
* 交换数组下标上的值
*
* @param arr 数组
* @param left 下标1
* @param right 下标2
*/
private static void swap(int[] arr, int left, int right) {
if (left == right) {
return;
}
arr[left] = arr[left] ^ arr[right];
arr[right] = arr[left] ^ arr[right];
arr[left] = arr[left] ^ arr[right];
}
public static void main(String[] args) {
int[] arr = {2,1,4,3,6,5,8,7,10,9,11,12,14,13,12};
int[] result = heapSort(arr, 3);
System.out.println(Arrays.toString(result));
}
}
若上面有看不懂的概念,请参照我的上一篇博客《算法基础入门 - 8、复杂排序算法-堆结构介绍+自定义堆+java堆》