1.topK
找前 K 个最大的,建小堆,堆的大小为K
找前 K 个最小的,建大堆,堆的大小为K
public class TopKTestDEmo {
/**
* 找前K个最大的元素
* @param array
*/
public static void topK(int[] array,int k){
//1.大小为K的小堆
PriorityQueue<Integer> minHeap = new PriorityQueue<>(k, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1-o2;
}
});
//2.遍历数组
for(int i = 0;i < array.length;i++){
if(minHeap.size()<k){
minHeap.offer(array[i]);
} else {
Integer top = minHeap.peek();
if(top!=null) {
if (array[i] > top) {
minHeap.poll();
minHeap.offer(array[i]);
}
}
}
}
//走到这里,minHeap中已经存储了前K个最大的
//打印
for(int i = 0; i<k;i++){
System.out.println(minHeap.poll());
}
}
/**
* 测试topK
*/
public static void main(String[] args) {
int[] array = {27,15,19,18,28,34,65,49,25,37};
topK(array,3);
}
}
2.找第K小的元素
建立大小为K的大堆,数组遍历完成后,留在堆顶的就是第K小的元素
3.堆排序
从小到大排序---->建大堆
从大到小排序---->建小堆
时间复杂度:O(n*logn) 无论好坏
空间复杂度:O(1)
/**
* 从小到大排序----》建大堆
*/
public class DuiPaiXv {
public static void adjustDown(int[] array,int parent,int len){
int child = 2*parent+1;
//child < len 说明有左孩子
while (child < len ){
//child+1<len ---》防止数组越界 判断当前是否有右孩子
if(child+1<len &&(array[child] < array[child+1])){
child++;
}
//走到这里,child 一定是左右孩子最大值的下标
//然后比较父亲和孩子谁大,做交换
if(array[child] > array[parent]){
int tmp = array[child];
array[child] = array[parent];
array[parent] = tmp;
//交换完了,还要再看下面的是否符合大堆
parent = child;
child = 2*parent+1;
}else {
//因为是从最后一个树开始调整的,
//所以只要this.elem[child] < this.elem[parent]
//就跳出循环,因为后边的那些肯定都已经是大根堆了
break;
}
}
}
//创建大根堆
public static void createBigHeap(int[] array){
for(int i = (array.length-1-1)/2;i>=0;i--){
adjustDown(array,i,array.length);
}
}
public static void heapSort(int[] array){
//1.创建大堆
createBigHeap(array);
//2.开始进行排序
int end = array.length-1;
while (end>0){
//1.交换
int tmp = array[0];
array[0] = array[end];
array[end] = tmp;
//2.向下调整
adjustDown(array,0,end);
//3.不管那个换下去的了
end--;
}
}
public static void main(String[] args) {
//测试
int[] array = {27,15,19,18,28,34,65,49,25,37};
heapSort(array);
System.out.println(Arrays.toString(array));
}
}