堆(Heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵完全二叉树的数组对象。
堆排序(英语:Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
1、将待排序的序列构造成一个大顶堆(升序大顶堆降序小顶堆)
2、将堆顶元素(根结点)和末尾元素进行互换。然后将剩余n-1个元素重新构造一个新的大顶堆
3、重复进行第2步操作便能得到一个有序的序列
在这说明下面代码中的一个问题:为什么从arr.length/2-1开始?
由于堆排序近似完全二叉树假设最后一个非叶子结点下标为n
当它的左子结点为末尾元素时:2n+1 = length-1 ==> n = length/2-1
当它的右子结点为末尾元素时:2n+2 = length-1 ==> n = length/2-(3/2)
在计算机中3/2是等于1的,所以从arr.length/2-1
可以在写代码之前看看这篇文章:二叉树顺序存储
import java.util.Arrays;
public class HeapSort {
public static void main(String[] args) {
int[] array = {4,6,1,2,9,8,3,5};
heapSort(array);
System.out.println(Arrays.toString(array));
}
/**
* 堆排序
*/
public static void heapSort(int[] arr){
//为什么从arr.length/2-1开始?
for (int i = arr.length/2-1; i >= 0 ; i--) {
adjustHeap(arr,i,arr.length);
}
for (int j = arr.length-1; j > 0; j--) {
int temp = arr[j];
arr[j] = arr[0];
arr[0] = temp;
/*为什么从0开始?
因为在第一次构建大顶堆后让堆顶元素和末尾元素进行交换
而对于其他的非叶子结点所对应的子树都是大顶堆就无需调整,
只需要堆顶元素(下标为0的非叶子结点)的子树调整成大顶堆
*/
adjustHeap(arr,0,j);
}
}
/**
* 构建大顶堆
* 注意:
* 这个方法并不是将整个树调整成大顶堆
* 而是以i对应的非叶子结点的子树调整成大顶堆
* @param arr 待调整的数组
* @param i 非叶子结点在数组中的索引(下标)
* @param length 进行调整的元素的个数,length是在逐渐减少的
*/
public static void adjustHeap (int[] arr,int i,int length){
/*取出当前非叶子结点的值保到临时变量中*/
int temp = arr[i];
/*j=i*2+1表示的是i结点的左子结点*/
for (int j = i * 2 + 1; j < length ; j = j * 2 + 1) {
if (j+1 < length && arr[j] < arr[j+1]){ //左子结点小于右子结点
j++; //j指向右子结点
}
if (arr[j] > temp){ //子节点大于父节点
arr[i] = arr[j]; //把较大的值赋值给父节点
//arr[j] = temp; 这里没必要换
i = j; //让i指向与其换位的子结点 因为
}else{
/*子树已经是大顶堆了*/
break;
}
}
arr[i] = temp;
}
}
[1, 2, 3, 4, 5, 6, 8, 9]
Process finished with exit code 0
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/m0_60117382/article/details/122794790
内容来源于网络,如有侵权,请联系作者删除!