堆的应用_topK算法和堆排序

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
            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));
    }
}

你可能感兴趣的:(堆排序)