最大堆的性质是除了根节点之外的所有节点(i)都需要满足A[PARENT(i)]>A[i],即其对应节点值小于其父节点对应值。
下面实现以数组int []a构建最大堆。
public class Heap {
public static int Left(int i)//返回左子结点
{return 2*i+1;}
public static int Right(int i)//返回右子节点
{return 2*i+2;}
public static void Max_Heapify(int []a,int i)//以数组a 和i为参数 i为数组内坐标
{
int left=Heap.Left(i);
int right=Heap.Right(i);
int most;//记录最大值的数组下标
int heapSize=a.length;
if((left<heapSize)&&(a[left]>a[i]))//判断left<heapSize 是为了判断left是否溢出数组
most=left;
else
most=i;
if((right<heapSize)&&(a[right]>a[most]))//!注意不是>a[i] 此处为了判断出 a[i]a[left]a[right]最大值
most=right;
if(most!=i)
{
Heap.swap(a, i, most);//交换 a[i]和a[most]
Max_Heapify(a,most);//交换完之后 递归调用 确保交换后的a[most]满足 A[PARENT(i)]>A[i]
}
}
public static void swap(int []a,int i,int j)//交换函数
{
int swap=a[i];
a[i]=a[j];
a[j]=swap;
}
public static void build_Max_Heap(int []a)//以数组int[]a为参数调用
{
for(int i=a.length/2;i>=0;i--)//从i=a.length/2开始调用Max_heapify()函数,因为 i>a.length/2的节点没有子节点。
{
Heap.Max_Heapify(a, i);
}
}
public static void main(String[] args) {
int []a={1,2,3,4,5,6,7};
Heap.build_Max_Heap(a);
for(int p:a)
System.out.println(p);//输出函数
}
}
输出:
7
5
6
4
2
1
3
总结:int []a={1,2,3,4,5,6,7}
初始时可以看为
- 开始从i=(a.length/2)=7/2=3开始,a[3]=4,无子节点 i--;
- i此时为2,a[2]=3. left[i]= 6,right[i]=7,a[most]=7,交换 3,7 得,之后还要对3递归判断 Max_Heapify(a,most);发现3符合其所在位置,i--.
- 此时i=1,a[1]=2,left[i]=4,right[i]=5,a[most]=5,交换2 ,5得之后还要对2递归判断 Max_Heapify(a,most);发现2符合其所在位置,i--.
- i=0;a[0]=1,left[i]=5,right[i]=7,a[most]=7,交换1,7得,之后还要对1递归判断 Max_Heapify(a,most);发现1 6 3 中6最大 所以 1 6 交换位置得
所以int[]a现在为{7,5,6,4,2,1,3},与输出相同。
如果该文章有任何错误,欢迎大家指正,谢谢。