在大数据集合中找出最小的K个数:维护一个大小为K的最大堆,遍历集合中的每个数字,和当前堆顶的最大数比较,如果大于堆顶数字表示该数不在最小K个数字的范围内,如果小于该顶值,用集合值替换堆顶值,然后对新的堆顶值做一个“下滤”操作(参考下面的percolateDown函数)。
堆排序的思路:针对一个数组,首先构建最大堆,从下往上对每个非叶子节点进行“下滤”操作,然后每次将最大值和当前末尾的元素交换,比如第i次将堆顶和倒数第i个元素交换值,再对堆顶做“下滤”操作,直到堆顶。Java实现代码如下:
public class HeapSort {
/**
* @param args
*/
public static void main(String[] args) {
int[] a = { 4, 1, 3, 2, 16, 9, 10, 14, 8, 7 };
heapSort(a);
for (int in : a) {
System.out.print(in + " ");
}
}
public static void heapSort(int[] a) {
buildMaxHeap(a);
for (int in : a) {
System.out.print(in + " ");
}
System.out.println();
for (int i = a.length - 1; i >= 0; i--) {
int temp = a[i];
a[i] = a[0];
a[0] = temp;
percolateDown(a, 0, i - 1);
}
}
public static void buildMaxHeap(int[] a) {
for (int i = getFirstNoLeaf(a.length - 1); i >= 0; i--) {
percolateDown(a, i, a.length - 1);
}
}
public static void percolateDown(int[] a, int begin, int last) {
int cur = a[begin];
int maxChild = getLeftChild(begin);
int i = begin;
for (; getLeftChild(i) <= last; i = maxChild) {
maxChild = getRightChild(i) <= last
&& a[getLeftChild(i)] < a[getRightChild(i)] ? getRightChild(i)
: getLeftChild(i);
if (a[maxChild] > cur) {
a[i] = a[maxChild];
} else {
break;
}
}
a[i] = cur;
}
public static int getFirstNoLeaf(int n) {
return (n - 1) / 2;
}
public static int getParent(int i) {
return (i + 1) / 2 - 1;
}
public static int getLeftChild(int i) {
return (i + 1) * 2 - 1;
}
public static int getRightChild(int i) {
return (i + 1) * 2;
}
}