排序-堆排序
排序必备知识
- 什么是大顶堆和小顶堆
- 大顶堆,根节点比左节点和右结点都大(用作升序排序)
- 小顶堆,根节点比左节点和右结点都小(用作降序排序)
- 堆排序的思想
- 根据是降序或升序排序构建大顶堆还是小顶堆
- 排序思想就是,每次从非空节点下标(i,根据当前未排序长度确定的,i = (未排序长度/2) - 1)开始到下标为0的去构建大顶推或者小顶堆
- 堆构建的过程,我们首先找到该下标得右结点(右结点下标2*i+2,这里需要做判断,是否有右结点也就是右结点是否已经排序),比较,替换
- 然后找到左子节点,比较,替换
- 时候i–继续重复,直到i为0
- 当下标i为0时,说明一趟结束,下标为0和下标最后一个(这里是动态变化,每一趟之后,最后一个下标就会减一)交换
- 未排序数列的长度减一
- 当未排序数列的长度为1时,结束排序
下面贴上大顶推和小顶推的排序实现
1、小顶堆排序java实现
public static void dumpSort(int[] arr) {
//当arr为空或者长度小于2的时候不需要排序,直接返回
if (arr.length <= 1) return;
for (int j = arr.length; j > 1; j--) {
//1、找到第一个非空的节点的下标
for (int i = j / 2 - 1; i >= 0; i--) {
//2、有可能没有右结点或者右结点已经排序
//2.1、若有右结点
int r = i * 2 + 2;
if (r < j) {
//2.2、右结点和根节点比较
if (arr[r] < arr[i]) {
arr[i] = arr[i] ^ arr[r];
arr[r] = arr[i] ^ arr[r];
arr[i] = arr[i] ^ arr[r];
}
}
//3、根节点和左节点比较
int l = i * 2 + 1;
if (arr[l] < arr[i]) {
arr[i] = arr[i] ^ arr[l];
arr[l] = arr[i] ^ arr[l];
arr[i] = arr[i] ^ arr[l];
}
}
//4、一趟结束后,找到最小值,沉到二叉树的最下面,交换值
arr[0] = arr[0] ^ arr[j - 1];
arr[j - 1] = arr[0] ^ arr[j - 1];
arr[0] = arr[0] ^ arr[j - 1];
}
}
- 大顶堆排序java实现
public static void bigDumpSort(int[] arr) {
if (arr == null || arr.length <= 1) {
return;
}
for (int i = arr.length; i > 1; i--) {
//1、每一趟构建堆
//j = i / 2 - 1计算非空节点下标,
int r;
int l;
for (int j = i / 2 - 1; j >= 0; j--) {
//2、从非空节点下标开始构建堆
//2.1、找到节点的右子结点
r = 2 * j + 2;
//2.2、判断是否存在右子节点或者右子节点
if (r < i) {//存在
//2.3、比较根节点和右结点
if (arr[r] > arr[j]) {
arr[j] = arr[j] ^ arr[r];
arr[r] = arr[j] ^ arr[r];
arr[j] = arr[j] ^ arr[r];
}
}
//3、一定存在左节点,比较左节点
l = 2 * j + 1;
if (arr[l] > arr[j]) {
arr[j] = arr[j] ^ arr[l];
arr[l] = arr[j] ^ arr[l];
arr[j] = arr[j] ^ arr[l];
}
}
//4 一趟结束,交换下标为0和下标最后一个元素
arr[0] = arr[0] ^ arr[i - 1];
arr[i- 1] = arr[0] ^ arr[i - 1];
arr[0] = arr[0] ^ arr[i - 1];
}
}