堆的应用_topK算法和堆排序

这篇博客介绍了如何利用堆数据结构实现寻找数组中前K个最大元素和最小元素的方法,以及堆排序的过程。文章提供了Java代码示例,包括建立小堆找最大值和大堆找最小值的实现,并详细解释了堆排序的调整过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值