堆排序思路: 1.先把数组中的元素依次传入构造为大根堆
2.交换根节点(数组第一个元素)和末尾的叶节点(数组最后一个元素)
3. 调整此时交换后的乱序大根堆
4. 调整完毕后,重复2,3步骤
5. 总结: 通过每次将大根堆中的栈顶元素和末尾元素交换,达到将该栈顶元素排好序的目的,依次 循环。
6. 要注意的点:
6-1 注意边界值的控制,设置区间[0, heapSize)为大根堆的范围,以此排除最后一个元素。
6-2 注意不要让当前结点的(交换后的栈顶元素)左右结点越界。
6-3 公式: i表示数组下标。i的左节点下标:2i+1。 右节点下标:2i+2。 父节点下标: (i - 1) / 2
/**
* @author cj
* @date 2019/7/8
* 完全二叉树:除根结点外,每个结点都是从左边开始产生 然后产生右边
*
* 数组中构造大根堆实质上是将数组中的元素依次加进来
* 调整当前元素在数组中的位置,使之对应在大根堆中的位置
*
* 堆排序思路:1.先把数组中的元素依次传入构造为大根堆
* 2.交换根节点(数组第一个元素)和末尾的叶节点(数组最后一个元素)
* 3. 调整此时交换后的乱序大根堆(a[0]到a[a.length - 2])
* 4. 调整完毕后,重复2,3步骤
* 注意:堆排序传的heapSize是数组最后一个数的下标,而该数是不属于堆的
*/
public class HeapSort {
public static void heapSort(int[] a) {
if(a == null || a.length < 2) {
return;
}
for (int i = 0; i < a.length; i++) {
heapInsert(a, i);//将每个元素依次插入,形成大根堆
}
int heapSize = a.length;
swap(a, 0, --heapSize);//将大根堆的根节点和最后一个节点交换
while(heapSize >= 1) {
//[0, heapSize-1]为堆,heapSize指向的元素不在堆内
heapify(a, 0, heapSize);//调整交换后的大根堆 heapSize指向当前堆右边界+1
swap(a, 0, --heapSize);//继续将大根堆的根节点和最后一个节点交换
}
}
//生成大根堆
public static void heapInsert(int[] a, int index) {
while(a[index] > a[(index - 1) / 2]) { //当前的值比父节点大则交换
swap(a, index, (index + 1)/2);
index = (index - 1) / 2; //交换后设置下标为父节点下标,继续比较
}
}
/**
* 传入一个大根堆[]a,该大根堆中的某个节点被替换了,index:被替换的节点的下标
* heapify()实现的功能是将该大根堆调整为正确的大根堆
* @param a 已经被排序为大根堆的数组a
* @param current 当前被替换的节点下标
* @param heapSize 指向堆的右边界 [index, heapSize)区间为大根堆
*/
public static void heapify(int[] a, int current, int heapSize) {
int leftNode = 2 * current + 1;//当前节点下标的左节点下标
while (leftNode < heapSize) { //抵达至当前堆的叶节点。不能等于最后一个元素,因为最后一个元素是被交换的元素,该元素不属于堆了
//先判断右节点是否存在,若存在则比较左节点和右节点的最大值 返回下标
int larger = leftNode + 1 < heapSize && a[leftNode+1] > a[leftNode] ?
leftNode + 1 : leftNode;//注意a[leftNode + 1] > a[leftNode]不能交换顺序
if(a[current] < a[larger]) {
swap(a, larger, current);
current = larger;//重置current指针的指向
leftNode = 2 * current + 1;//指向current的下一个左节点
} else {
break;//当前的数大于等于a[larger],堆排序中等于a[larger],不会大于
}
}
}
public static void swap(int[] a, int i, int j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
public static void main(String[] args) {
int[] a= new int[]{4,3,1,7,2};
heapSort(a);
for (int i = 0; i < a.length; i++) {
System.out.println(a[i]);
}
}
}