数据结构之堆的应用

news/2024/5/20 6:29:27 标签: 开发语言, 数据结构, 算法, java,

系列文章目录

数据结构_crazy_xieyi的博客-CSDN博客


文章目录

  • 前言
  • 一、Top-k问题
  •         1.前K个最小数(第k个最小数)
  •         2.前K个最大数(第K个最大数)
  • 二、排序
    • 1.从小到大排序(建大根
    • 2.从大到小排序(建小跟

前言

JDK1.8 中的 PriorityQueue底层使用了数据结构作为底层结构 封装了优先级队列。
(向下调整)的时间复杂度O(N):

向上调整建的时间复杂度为O(nlogn).

一、Top-k问题

示例:在给定的一个数组中求前K个最小的数

第一种思路:把给定的数组直接进行排序,然后前K个一定是最小的数;

java"> public int[] getLeastNumbers(int[] arr, int k) {
           Arrays.sort(arr);
            int[] str = new int[k];
            for (int i = 0; i < k; i++) {
                 str[i] = arr[i];
            }
            return str;
    }

显然这种方式是不可取的,如果数据量非常大,排序就不太可取了(可能数据都

不能一下子全部加载到内存中 ) 。最佳的方式就是用来解决。
第二种思路:把整个数组整体建小根,然后依次弹出K个顶的数据。
java">public static int[] smallestK(int[] arr, int k) {
        //1. 建立一个小根
        PriorityQueue<Integer> minHeap = new PriorityQueue<>();
        //2、取出数组当中的每个元素,存放到小跟当中
        for (int i = 0; i < arr.length; i++) {
            minHeap.offer(arr[i]);
        }
        //3.弹出K个元素,存放到数组当中,返回即可
        int[] tmp = new int[k];
        for (int i = 0; i < k; i++) {
            tmp[i] = minHeap.poll();
        }
        return tmp;
    }

但是你会发现,这种方式虽然可以,但是时间复杂度比较高,还是不可取得。整体建的时间复杂度为o(n),然后弹出K次时间复杂度为Klogn,则总体时间复杂度为 O(N + Klogn);

第三种思路:

1. 用数据集合中前 K个元素来建 k 个最大的元素,则建小 k 个最小的元素,则建大
2. 用剩余的 N-K 个元素依次与顶元素来比较,不满足则替换顶元素
将剩余 N-K 个元素依次与顶元素比完之后,中剩余的 K 个元素就是所求的前 K 个最小或者最大的元素。
下面还是用上面求前K个最小的数为例:
java">        public int[] getLeastNumbers(int[] arr, int k) {
           PriorityQueue<Integer> minHeap = new PriorityQueue<>(new Comparator<Integer>() {
                @Override
                public int compare(Integer o1, Integer o2) {
                    return o2.compareTo(o1);
                }
            });
            if (arr == null || k == 0)return new int[0];
            //用K个元素,先建立一个大根
            for (int i = 0; i < k; i++) {
                minHeap.offer(arr[i]);
            }
            //剩余元素与元素进行比较
            for (int i = k; i < arr.length; i++) {
                if (arr[i] < minHeap.peek()){
                    minHeap.poll();
                    minHeap.offer(arr[i]);
                }
            }
            //返回前K个元素
            int[] str = new int[k];
            for (int i = 0; i < k; i++) {
                str[i] = minHeap.poll();
            }
            return str;
        }

此时时间复杂度为:k + (n-k)logk ,约等于nlogk。

那么现在有一个小问题,就是第K个最小的怎么求?

其实这一点非常简单,求第K个最小的,只需要弹出一次就好了,因为此时是大跟,那么第K个最小的肯定就是顶的元素。

二、排序

排序即利用的思想来进行排序,总共分为两个步骤:
 1.
升序:建大
降序:建小
2. 利用删除思想来进行排序
删除中都用到了向下调整,因此掌握了向下调整,就可以完成排序。
java">    /**
     * 时间复杂度:
     *  O(n) + O(n*logn) 约等于 O(nlogn)
     *  空间复杂度:O(1)
     */
    public void heapSort() {
        //1.建立大根 O(n)
        createHeap();
        //2.然后排序
        int end = usedSize-1;
        while (end > 0) {
            int tmp = elem[0];
            elem[0] = elem[end];
            elem[end] = tmp;
            shiftDown(0,end);
            end--;
        }
    }

    private void shiftDown(int root,int len) {
        int child = root*2 + 1;
        while (elem[child] > elem[root]){
            if (child+1 < len && elem[child] < elem[child+1]){
                child++;
            }
            if (elem[child] > elem[root]){
                int temp = elem[child];
                elem[child] = elem[root];
                elem[root] = temp;
                child = root;
                root = (child-1)/2;
            }else {
                break;
            }
        }
    }

时间复杂度: O(n) + O(n*logn) 约等于 O(nlogn)
空间复杂度:O(1)


http://www.niftyadmin.cn/n/915.html

相关文章

cppcheck静态代码检查工具使用教程

0 背景 最近调研了几款 c/c 代码静态检查工具&#xff0c;包括 cppcheck、cpplint、cppdepend、splint、tscancode、sonaqube 等&#xff0c;对比后认为 cppcheck 使用起来最方便&#xff0c;检查内容相对全面&#xff0c;支持多平台应用&#xff08;linux 和 windows&#xf…

ubuntu下快捷指令和bashrc文件配置

快捷指令 source activate labelme sudo nautilus sudo chmod u+x * ------------------------------------------------------------------------------------------------------------- https://github.com/LCAS/CMP9767M/wiki/useful-resources https://github.com/LCAS…

【从零到一的Raspberry】树莓派踩坑实录(一)系统安装与简单开发

写在前面 本系列作为树莓派上手记录&#xff0c;同时将本人的踩坑以及参考进行记录汇总&#xff0c;必要时罗列出小组分工&#xff0c;作为《嵌入式软开》小组参考文件。 0 硬件准备 名称描述树莓派3B支持wifi&#xff0c;包含了散热器、外壳、电源线等配件网线感谢王emo同学…

【无标题】

收单外包机构如何开展及提升评级工作 依据历年经验&#xff0c;今年的收单外包机构的评级工作预估为11月份。该评级结果越来越得到收单机构和商业银行的重视&#xff0c;其一般要求与评级为B&#xff08;含&#xff09;以上的外包机构进行合作。另据公开报道&#xff0c;这几年…

linux日常常用命令

linux日常常用命令介绍——简单明了不啰嗦一、解压缩文件常用命令1.1 解压文件命令1.2 文件传输命令二、常见的实用命令2.1 find、locate 命令2.1.1 find 命令2.1.2 locate 命令2.2 grep 命令2.2.1 查询文件 或 内容2.2.2 查询进程等三、查看端口情况、进程情况四、查看运行的服…

一次服务器非法重启后导致的故障排查记录

作者&#xff1a;JackTian 来源&#xff1a;公众号「杰哥的IT之旅」 ID&#xff1a;Jake_Internet 转载请联系授权&#xff08;微信ID&#xff1a;Hc220088&#xff09; 原文地址&#xff1a;一次服务器非法重启后导致的故障排查记录 大家好&#xff0c;我是杰哥。 前段时间遇…

python 基于PHP在线音乐网站

随着时代的发展,人们的生活水平越来越高,相对应的对精神世界的追求也越来越多,而音乐一直以来一直是人们追求美好生活的象征,它不仅可以陶冶人们的情操还可以美化人们的灵魂,音乐也一直是千百年来人们不断追求的一个精神文明的产物,为了能够让更多的人找到自己喜欢的音乐,我开发…

2022 年辽宁省大学生程序设计竞赛 个人题解

title : 2022 年辽宁省大学生程序设计竞赛 date : 2022-10-25 tags : ACM,练习记录 author : Linno 2022 年辽宁省大学生程序设计竞赛 题目链接&#xff1a;https://ac.nowcoder.com/acm/contest/43937 进度&#xff1a;10/13 质量比较差的场&#xff0c;后三题是错的&#…