堆排序思想
- 构建初始堆,将待排序列构成一个大顶堆(或者小顶堆),升序大顶堆,降序小顶堆;
- 将堆顶元素与堆尾元素交换,并断开(从待排序列中移除)堆尾元素。
- 重新构建堆。
-
代码实现
```java public class HeapSort {
public static void main(String[] args) {
int[] arr = {49, 38, 65, 97, 76, 13, 27, 49};
// int[] arr = {16, 7, 3, 20, 17, 8};
heapSort(arr);for(int i=0; i<arr.length; i++)System.out.print(arr[i] + " ");
}
//创建堆 private static void heapSort(int[] arr) {
//从第一个非叶子节点开始调整,从下至上、从右至左//这样可以保证最大的那个数永远会被往上调整for(int i=(arr.length-1)/2; i>=0; i--){adjustHeap(arr, i, arr.length);}//交换堆顶元素与末尾元素,调整堆结构for(int i=arr.length-1; i>0; i--){int temp = arr[0];arr[0] = arr[i];arr[i] = temp;adjustHeap(arr, 0, i);}
}
//调整堆 /*
parent: 父节点length: 待排序列的尾元素索引
*/ private static void adjustHeap(int[] arr, int parent, int length) {
//当前要调整的元素int temp = arr[parent];//左孩子int lChild = 2 * parent + 1;while(lChild < length){//右孩子int rChild = lChild + 1;if(rChild<length && arr[lChild]<arr[rChild])lChild++; //左孩子指向的是孩子节点里最大的那个//如果父结点的值已经大于孩子结点的值,则直接结束//因为孩子结点已经是调整过的,可以保证比所有孙子节点都要大if(temp >= arr[lChild])break;//把孩子结点的值赋给父节点arr[parent] = arr[lChild];//*注:虽然没有进行“交换”的步骤,但是每次比较的对象都是“temp”,所以相当于交换//向下调整,防止当前交换影响子堆的结果//整个操作相当于孩子结点逐个覆盖父节点,最后将最顶上的祖先结点的值赋给最下面的结点parent = lChild;lChild = 2 * lChild + 1;}arr[parent] = temp;
}
} ```
