堆:
- 是具有以下性质的完全二叉树:每个节点的值都大于或等于其左右孩子节点的值,乘为大顶堆;或每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。
特点:
- 大顶堆:arr[i] >= arr[2i+1] && arr[i] >= a[2i+2]
- 小顶堆: arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]
- 下标从0开始。
基本思想:
- 将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就是最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的最小值。反复执行即可得到一个有序序列。
代码实现:(大顶堆) - 代码实现步骤:
- 初始化堆,自下而上,自右向左从非叶子节点开始。
- (非叶子节点:(length-1)/2【下标从0开始】
- 父节点:parent,左子节点=2 ×parent + 1, 右子节点=左子节点+1=2×parent + 2【下标从0开始】
- 堆的位置调整:
- 判断当前节点与左右子节点大小,进行位置变换,位置变换后,获取改变了位置的子节点,作为父节点继续进行比较。直到不存在子节点。
package com.zhang.Prac;
public class HeapSort {
public static void main(String[] args) {
int[] arr = {16, 7, 3, 20, 17, 8};
heapSort(arr);
for (int i : arr){
System.out.println(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[i];
arr[i] = arr[0];
arr[0] = temp;
//重新对堆进行调整
adjustHeap(arr, 0 , i);
}
}
/**
* 调整堆
* @param arr 待排序列
* @param parent 父节点
* @param length 待排序列尾元素索引
*/
private static void adjustHeap(int[] arr, int parent, int length){
//将temp作为父节点
int temp = arr[parent];
//左孩子
int lChild = 2 * parent + 1;
while (lChild < length){
//右孩子
int rChild = lChild + 1;
//如果有右孩子节点,并且右孩子节点的值大于左孩子节点,则选取右孩子节点
// if (rChild < length){
// System.out.println(arr[lChild] +" "+ arr[rChild]);
// }
if(rChild < length && arr[lChild] < arr[rChild]){
lChild ++;
}
//如果父节点的值已经大于孩子结点的值,则直接结束
if(temp >= arr[lChild]){
break;
}
//把孩子节点的值赋给父节点
arr[parent] = arr[lChild];
//选取孩子节点的做孩子结点,继续向下筛选
parent = lChild;
lChild = 2 * lChild + 1;
}
// System.out.println(temp);
arr[parent] = temp;
}
}