对于海量数据中,数量量大于内存可接受的数据,需要选择出最小的k个数,内存无法对所有的数据进行排序,因此可采用一个大小为k的堆容器b[],进行辅助排序。对于原始数据数组a[],大小为n,n>>k。
初始时将n个元素中的前k个元素存储在堆容器b[]数组中,并对其进行堆排序,建立大顶堆(所有父节点的元素大于子节点)。堆排序是从第一个非叶子节点开始进行调整,此节点与其子节点进行比较,若子节点大于父节点,则将父节点与子节点进行交换,这一交换可能使子节点的子树不满足大顶堆的特点,因此需要递归重新调整子树。
然后对n个元素剩下的所有元素进行操作,若元素大于大顶堆的堆顶元素,则对其不进行任何操作。反之,该元素替换堆顶元素,并进行堆调整。
最后堆容器b[]中的元素便是最小的k个元素。
时间复杂度O(nlogk),优点:不需要改变输入数组,适合处理海量数组。
public class GetLeastNumbers {
public static void main(String[] args) {
// TODO Auto-generated method stub
int a[]={4,5,1,6,2,7,3,8,0};
int b[]=get_min_k(a,4);
for(int i=0;i<b.length;i++)
{
System.out.println(b[i]);
}
}
public static int[] get_min_k(int a[],int k)
{
int b[]=new int[k];
if(a.length<=k)
return a;
for(int i=0;i<k;i++)
b[i]=a[i];
for(int i=(k-1)/2;i>=0;i--)
adjustHeap(b,i);
for(int i=k;i<a.length;i++)
if(a[i]<b[0])
{
b[0]=a[i];
adjustHeap(b,0);
}
return b;
}
private static void adjustHeap(int[] b, int i) {
// TODO Auto-generated method stub
int index=i;
int left=2*i+1;
int right=2*i+2;
if(left<b.length&&b[index]<b[left])
index=left;
if(right<b.length&&b[index]<b[right])
index=right;
if(index!=i)
{
int temp=b[i];
b[i]=b[index];
b[index]=temp;
adjustHeap( b, index);
}
}
}