堆排序
以后可能需要不插图,所以他单独分出来
public void heapSort(int[] arr, boolean asc) {
//升序
if(asc) {
for(int i = 0; i < arr.length; i++) {
while(!fixMaxHeap(arr,0, i));
int temp = arr[0];
arr[0] = arr[arr.length - i -1];
arr[arr.length - i -1] = temp;
}
} else {
for(int i = 0; i < arr.length; i++) {
while(!fixMinHeap(arr,0, i));
int temp = arr[0];
arr[0] = arr[arr.length - i -1];
arr[arr.length - i -1] = temp;
}
}
}
//维护小顶堆
private boolean fixMinHeap(int[] arr, int idx, int legal) {
if(2 * idx + 1 > arr.length - 1 && 2 * idx + 2 > arr.length - 1) return true;
int lVal = leftChild(arr, idx, legal);
int rVal = rightChild(arr, idx, legal);
// 当一个数字小于等于 他的两个子节点,并不能代表这个堆就已经是一个标准的大顶堆。 注意我的 与符号 用的是 & 两个分支都要进行维护
if(arr[idx] <= lVal && arr[idx] <= rVal) return fixMinHeap(arr, 2 * idx + 1, legal) & fixMinHeap(arr, 2 * idx + 2, legal);
else if(lVal < rVal) {
arr[2 * idx + 1] = arr[idx];
arr[idx] = lVal;
fixMaxHeap(arr, 2 * idx + 1, legal);
}else {
arr[2 * idx + 2] = arr[idx];
arr[idx] = rVal;
fixMaxHeap(arr, 2 * idx + 2, legal);
}
return false;
}
//维护大顶堆
private boolean fixMaxHeap(int[] arr, int idx, int legal) {
if(2 * idx + 1 > arr.length - 1 && 2 * idx + 2 > arr.length - 1) return true;
int lVal = leftChild(arr, idx, legal);
int rVal = rightChild(arr, idx, legal);
// 当一个数字大于等于 他的两个子节点,并不能代表这个堆就已经是一个标准的大顶堆。 注意我的 与符号 用的是 & 两个分支都要进行维护
if(arr[idx] >= lVal && arr[idx] >= rVal) return fixMaxHeap(arr, 2 * idx + 1, legal) & fixMaxHeap(arr, 2 * idx + 2, legal);
else if(lVal > rVal) {
arr[2 * idx + 1] = arr[idx];
arr[idx] = lVal;
fixMaxHeap(arr, 2 * idx + 1, legal);
}else {
arr[2 * idx + 2] = arr[idx];
arr[idx] = rVal;
fixMaxHeap(arr, 2 * idx + 2, legal);
}
return false;
}
private int rightChild(int[] arr, int idx, int legal) {
int n = arr.length - 1 - legal;
//返回他自身就是为了让他继续递归
if((idx * 2 + 2) > n) return arr[idx];
return arr[idx * 2 + 2];
}
private int leftChild(int[] arr, int idx, int legal) {
int n = arr.length - 1 - legal;
//返回他自身就是为了让他继续递归
if((idx * 2 + 1) > n) return arr[idx];
return arr[idx * 2 + 1];
}