原理
堆排序的思想要复杂些,首先,我们要理解什么是堆。提到堆,就得先搞明白一个概念:完全二叉树。
完全二叉树
完全二叉树是一种特殊的二叉树,叶子结点只能出现在最下层和次下层,且最下层的叶子结点集中在树的左部。(先上后下,先左后右)
堆
所以,堆和完全二叉树有什么关系呢?其实堆就是一种特殊的完全二叉树。它需要满足一个条件:对于任意一个子节点来说,均不大于其父节点的值,即为大顶堆;同理,不难理解,对于任意一个子节点来说,均不小于其父节点的值,即为小顶堆。
堆排序
明白了什么是堆,就很容易理解堆排序的原理了。首先以大顶堆为例,堆顶的元素是所有元素中最大的元素,那么把堆顶的元素拿走,再次调整使得剩下的元素又成为一个大顶堆,那么堆顶的元素就是第二大的元素。依此类推,我们每一轮拿出的堆顶元素就已经排好序了。
代码
说起来也不是很难,其实最关键的步骤就是建堆和调整堆。
public class HeapSort {
public static void sort(int[] arr) {
//从第一个非叶子节点开始 arr.length/2 - 1。
for(int i = arr.length/2 - 1;i >= 0; i--) {
adjustHeap(arr, i, arr.length);
}
for(int j = arr.length - 1;j > 0; j--) {
swap(arr, 0, j);
adjustHeap(arr, 0, j);
}
}
/**
*
* @title: adjustHeap
* @description: 调整数组成堆
* @param arr
* @param i
* @param length
*/
private static void adjustHeap(int[] arr, int i, int length) {
int temp = arr[i];//保存当前节点
for(int k = 2 * i + 1;k < length; k = 2 * k + 1) {
if(k + 1 < length && arr[k] < arr[k + 1]) {
k++;
}
if(arr[k] > temp) {
swap(arr, i, k);
i = k;
}else {
break;
}
}
}
/**
*
* @title: swap
* @description: 交互数组中的两个元素
* @param arr 目标数组
* @param j 目标下标
* @param k 目标下标
*/
private static void swap(int[] arr, int j, int k) {
int temp = arr[j];
arr[j] = arr[k];
arr[k] = temp;
}
}
网友评论