堆是具有以下性质的完全二叉树:
如下图所示:
那么话又说回来了,什么是完全二叉树呢?
要想知道什么是完全二叉树,首先得知道什么满二叉树。
同时,我们对堆中的结点按层进行编号,将这种逻辑结构映射到数组中就是下面这个样子
简单的说对于二叉树中的任意一个节点,假设它的下标为i,那么它左孩子的节点在数组中的下标就是2i+1,而其右孩子节点的下标就是2i+2
因此对于大顶堆来说满足一下的条件:
大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]
对于小顶堆来说满足
小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]
package sort;
import java.util.Arrays;
public class HeapSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr= {4,6,8,5,9};
System.out.println(Arrays.toString(arr));
heapSort(arr);
System.out.println(Arrays.toString(arr));
}
//堆排序
public static void heapSort(int[] arr)
{
//将无序的数组构造成一个堆,根据升序或者降序选择大顶堆或者小顶堆
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;
adjustHeap(arr, 0, j);
}
}
//将数组(二叉树),调整成一个大顶堆
/*
* 完成将以i对应的非叶子节点调整成大顶堆
*
* i表示非叶子节点在数组中的索引
* len代表对多少个元素进行调整,length在不断的减少
*
*/
public static void adjustHeap(int[] arr,int i,int length)
{
int temp=arr[i];//取出当前元素的值,保存为临时变量
//开始调整
//k指向的i这个节点的左子节点
for(int k=i*2+1;k<length;k=k*2+1)
{
if(arr[k]<arr[k+1]&&k+1<length)//左子节点小于右子节点的值
{
k++;//k指向右子节点
}
if(arr[k]>temp)//子节点大于父节点
{
arr[i]=arr[k];//把较大的值赋值给当前的节点
i=k;//i指向k,继续循环比价
}
else
{
break;//因为是从下至上的比较
}
}
//当for循环结束之后已经将以i为父节点的最大值放在i的位置,局部大顶堆
arr[i]=temp;//放到调整后的位置
}
}
原文:https://www.cnblogs.com/mengxiaoleng/p/11729131.html