在《程序员编程艺术》中有求最小k的最大堆排序算法,通过JAVA进行了实现,并输出结果。
在实现的过程中,尤其是最大堆中,自顶向下的更新是最容易出错的,本程序中巧妙的使用i和j的关系(父节点和子节点),而后采用while循环,依次以小三角,更新。
实现程序如下:
package minK;
import java.util.Scanner;
/**
* 2015年4月9日 10:18:29
* @author 决明子胤
*此程序验证了最大堆排序,最小堆排序同理
*/
public class MaxHeap {
int a[]={5,8,10,9,2,6,15,20,7};
int nn=a.length;
int k;
public void FixUp(int a[],int i) {
int temp;
temp=a[i];
while (i>0) {
int j=(i-1)/2;
if (a[i]<=a[j]) {
break;
}else {
a[j]=a[i];
i=j;
}
}
a[i]=temp;
}
public void Add(int a[],int i,int num){
a[i]=num;
FixUp(a,i);
}
//输入K的值
public void Getk() {
Scanner in=new Scanner(System.in);
System.out.println("请输入K的值");
k=in.nextInt();
}
public void FixDown(int a[],int j,int n) {
int temp=a[j];//j为父节点
while (j<n&&(2*j+1)<n) {
int i=2*j+1;//子节点
if ((i+1)<n&&a[i]<a[i+1]) {
i=i+1;
}
if (temp>a[i]) {
break;
}
else {
a[j]=a[i];
a[i]=temp;
j=i;
}
}
}
//顶点删除
public void Delete(int a[],int j,int n) {
int temp=a[0];
a[0]=a[n];
a[n]=temp;
FixDown(a,0,n-1);
}
//堆化数组,其实就是对其小范围内自顶向下的重新排列
public void MakeMaxHeap(int a[],int i,int n) {
for (int j = (i-1)/2; j >=0; j--){//构造堆其实就是自小三角顶向下的一个重构
FixDown(a,j,n);
}
}
public void Sort(int a[],int i,int n) {
for(i=n;i>0;i--){
int temp=a[0];
a[0]=a[i-1];
a[i-1]=temp;
FixDown(a,0,i-1);//该问题困扰我几个小时,后终于找出原因,在交换取值之后,边界相应的应该-1
}
}
//输出显示结果
public void Out(int b[],int k) {
System.out.println("输出结果为:");
for (int i = 0; i <k; i++) {
System.out.print(b[i]+" ");
}
}
public static void main(String[] args) {
MaxHeap abc=new MaxHeap();
abc.Getk();
abc.MakeMaxHeap(abc.a,8,9);
abc.Out(abc.a,9);
abc.Sort(abc.a,8,9);
abc.Out(abc.a,abc.k);
}
}
输出结果:
请输入K的值
2
输出结果为:
20 9 15 8 2 6 10 5 7 输出结果为:
2 5