读《程序员编程艺术》之自造Java版本----最大堆排序实现最小K问题

在《程序员编程艺术》中有求最小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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值