public interface Sort{
public void sort(int[] arr);
public void sortDesc(int[] arr);
}
package Sort.Function;
/**
* 堆排序
*
*/
public class HeapSort implements Sort{
@Override
/**
* 大到小
*/
public void sortDesc(int[] arr) {
doSort(arr, false);
}
@Override
/**
* 小到大
*/
public void sort(int[] arr) {
doSort(arr, true);
}
public void doSort(int[] arr, boolean asc) {
if (arr == null) {
return;
}
int maxIndex = arr.length - 1;
// 先调整为最大堆/最小堆, 最大堆用来正序(小到大),最小堆用来反序(大到小)
// 从最后一个子节点的父节点开始
for (int i = (maxIndex - 1) / 2; i >= 0; i--) {
adjustHeap(arr, i, maxIndex, asc);
}
// 调整之后 arr[0]为最大值/最小值
for (int i = 0; i < arr.length; i++) {
// 替换arr[0]和arr[最后一个位置],即将 最大的/最小的 放到数组最后边
swapArray(arr, 0, maxIndex - i);
// 调整第一个位置,再次调整为最大堆/最小值
adjustHeap(arr, 0, maxIndex - i - 1, asc);
}
}
/**
* 替换
*
*/
private void swapArray(int[] b, int i, int j) {
int tmp = b[i];
b[i] = b[j];
b[j] = tmp;
}
/**
* 从i元素向下调整,将最大的数提到i位置
*
*/
public void adjustHeap(int[] arr, int i, int maxindex, boolean asc) {
int parent = i;// 父元素下标
int child = parent * 2 + 1;// 左子元素下标
while (child <= maxindex) {
// 根据排序方式(大序 小序) 从左右节点中选择更小或更大的
if ((child + 1) <= maxindex && selectRightOne(arr, child, asc)) {
child = child + 1;
}
// 是否需要替换父子节点
if (needSwap(arr, parent, child, asc)) {
swapArray(arr, parent, child);
}
// 向下一层
parent = child;
child = parent * 2 + 1;
}
}
/**
* 正序 父节点小需要替换, 反序 父节点大需要替换
*/
private boolean needSwap(int[] arr, int parent, int child, boolean asc) {
return asc ? arr[parent] < arr[child] : arr[parent] > arr[child];
}
/**
* 正序 挑选左右节点更大的那个, 反序,挑选小的
*/
private boolean selectRightOne(int[] arr, int child, boolean asc) {
return asc ? arr[child] < arr[child + 1] : arr[child] > arr[child + 1];
}
}
public class HeapSortTest{
public static void main(String[] args) {
int[] a = {4,1,9,15,1,12,3};
Sort heapSort = new HeapSort();
heapSort.sortDesc(a);// 堆排序asc
printArr(a);
}
private static void printArr(int[] arr) {
StringBuilder sb = new StringBuilder();
for (int j = 0; j < arr.length; j++) {
sb.append(" " + arr[j]);
}
System.out.println(sb.length() > 0 ? sb.substring(1) : sb.toString());
}
}