堆排序用法
因为堆结构只保证 根节点比双子节点都大或小
1 求最小的n个数:
构建n个数的大顶堆,依次弹出堆顶再往下调整(用例省略)
2 求最大的n个数:
构建n个数的小顶堆,依次弹出堆顶再往下调整(用例省略)
3 求第n大的数:
构建所有元素的大顶堆,依次弹出堆顶,堆底放到堆顶并向下调整,重复n次
用例:
public int findKth(int[] a, int n, int K) {
ArrayList<Integer> list = (ArrayList<Integer>)Arrays.stream(a).boxed().collect(
Collectors.toList());
//大根堆
buildHeap(list);
int maxK = 0;
for (int i = 0 ; i < K ; i++) {
maxK = list.get(0);
//顶换到底部
swap(list, list.size() - 1, 0);
//删除队尾元素
list.remove(list.size() - 1);
//向下调整
shiftDown(list, 0);
}
return maxK;
}
private void buildHeap(ArrayList<Integer> a) {
int len = a.size();
for (int i = len / 2 - 1 ; i >= 0; i--) {
shiftDown(a, i);
}
}
private void shiftDown(ArrayList<Integer> a, int i) {
System.out.println(a.size() + ";" + i);
int len = a.size() - 1;
int maxIndex = 0;
if (2 * i + 2 > len) {
//没有右子节点
if(2*i+1 > len) {
return;
}else{
//有左子节点
maxIndex = 2 * i + 1;
}
} else {
//有双子节点
if (a.get(2 * i + 1) < a.get(2 * i + 2)) {
//左子节点小于右子节点
maxIndex = 2 * i + 2;
} else {
//左子节点大
maxIndex = 2 * i + 1;
}
}
if (a.get(i) < a.get(maxIndex)) {
swap(a, i, maxIndex);
shiftDown(a, maxIndex);
}
}
private void swap(ArrayList<Integer> a, int i, int j) {
int temp = a.get(i);
a.set(i, a.get(j));
a.set(j, temp);
}
浙公网安备 33010602011771号