首页 > 编程语言 >Topk问题与堆排序(Java数据结构)

Topk问题与堆排序(Java数据结构)

时间:2024-10-17 17:19:47浏览次数:3  
标签:arr Java int 小堆 堆排序 大堆 length Topk public

前言:

        接触完堆之后,也逐渐对堆了如指掌,最后再来讨论一下两个问题。

        有如下场景:

        1、全国有几千所大学,我如何能够快速找出排名前10的大学?

        2、我如何对这10所大学排好序?

        为了用堆解决问题,接下来我们就来一起学习Topk问题的解法与堆排序!

TopK问题:

        我们需要借助堆完成找到最大或最小的集合。

        现在我们开始思考一个问题,假如我这会有20个数据,我如何才能找到最大或最下的三个数据?

        第一步:要创建大小为3的堆。

        那么这个堆应该创建成大堆还是小堆呢?

        答案是:如果要找最大的3个,就创建大小为3的小堆。

                       如果要找最小的3个,及创建大小为3的大堆。

        很多人此时就很难想,本能地以为我找小就要创建小堆,找大就要创建大堆,这个观点是不对的,为什么?

        可以画图解释:

        

此时自然而然该堆中存放的就是最大的3个元素!!

如果换做是大堆,存放的除了堆顶是最大的元素之外其他的不符合条件!!!

找到最大的三个元素:

建小堆:

接下来就来尝试自己写写代码:

        

    public static void main(String[] args) {
        int arr[] = {12,1,3,32,13,16,17,18,10,44};
        PriorityQueue<Integer> q = new PriorityQueue<>();
        //找到最大的3个元素
        for(int i = 0;i<3;i++) {
            //插入3个元素默认建小堆
            q.offer(arr[i]);
        }
        for(int i = 3;i<arr.length;i++) {
            if(arr[i] >q.peek()) {
                q.poll();
                q.offer(arr[i]);
            }
        }
        for(int i = 0;i<3;i++) {
            System.out.print(q.poll()+" ");
        }
    }

结果如下:

找到最小的三个元素:

        建大堆:

        自己写一个比较器,并传入参数。

class IntCom implements Comparator<Integer> {
    @Override
    public int compare(Integer o1, Integer o2) {
        return o2-o1;
    }
}
public class Test1 {
    public static void main(String[] args) {
        int arr[] = {12,1,3,32,13,16,17,18,10,44};
        PriorityQueue<Integer> q = new PriorityQueue<>(new IntCom());
        //找到最大的3个元素
        for(int i = 0;i<3;i++) {
            //插入3个元素默认建小堆
            q.offer(arr[i]);
        }
        for(int i = 3;i<arr.length;i++) {
            //注意修改大于号
            if(arr[i] <q.peek()) {
                q.poll();
                q.offer(arr[i]);
            }
        }
        for(int i = 0;i<3;i++) {
            System.out.print(q.poll()+" ");
        }
    }
}

堆排序:

        有人说,大堆一定是从大到小分布的,小堆一定是从小到大排布的吗?

        答案肯定不是,大堆你只能确定每棵子树的根节点一定大于孩子节点,小堆也一样,没棵子树的根节点一定小于孩子节点,但是不能确定左孩子和右孩子的大小关系。

        此时要想实现堆排序,有以下几个步骤:

        1、要想排升序,得是大堆。(把最大的数逐渐沉底)

        2、要想排降序,得是小堆。(把最小的数逐渐沉底)

        3、每次找到将堆顶和堆底的元素进行交换,之后对剩下的元素继续向下调整为大(小)堆。

了解了理论,接下来就来实践一下:

将数组{12,1,3,32,13,16,17,18,10,4}排成降序:

代码如下:

    public static void sitfDown(int[] arr,int parent,int len) {
        int child = parent*2+1;
        while(child < len) {
            if(child+1<len && arr[child+1]<arr[child]) {
                child++;
            }
            if(arr[child]<arr[parent]) {
                swap(arr, child, parent);
                parent = child;
                child = parent * 2 + 1;
            }else {
                break;
            }
        }
    }
    public static void swap(int[] arr,int child, int parent) {
        int tmp = arr[parent];
        arr[parent] = arr[child];
        arr[child] = tmp;
    }
    public static void main(String[] args) {
        int arr[] = {12,1,3,32,13,16,17,18,10,44};
        //重新组成小堆
        for(int i = (arr.length-1-1)/2;i>=0;i--) {
            sitfDown(arr,i,arr.length);
        }
        //进行排序
        for(int i = 0;i< arr.length;i++) {
            swap(arr,0,arr.length-1-i);
            sitfDown(arr,0, arr.length-1-i);
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+" ");
        }
    }

升序大家可以自己可以尝试尝试!!

标签:arr,Java,int,小堆,堆排序,大堆,length,Topk,public
From: https://blog.csdn.net/m0_75235246/article/details/142934616

相关文章

  • Java数据结构二叉树面试题精华(画图详解)
    前言:    针对二叉树,因为涉及到递归,需要跟多的练习强化递归的思想,其中也包括需要画图理解一些想不通的问题来提升自己!    一下面这些题为例,一起来提升自己的逻辑思维能力!(可能其中一些题已经写过,但是希望能再写一遍有助于提高代码能力)相同的树:      ......
  • 一个月学会Java 第20天 多线程
    Day20多线程线程,很重要的概念,因为我们的CPU假如是intel或者amd的都是说一核二线程,假如你的电脑是8核的cpu那基本上就是16线程,如果你的mac的M芯片自然是几核就是几线程。想要查看自己的电脑是几个线程的我们有几种方法,一种直接使用Java运行一串代码,其次我们可以看任务管......
  • 【2024华为OD-E卷-100分-内存资源分配】(题目+思路+Java&C++&Python解析+在线测试)
    在线评测链接题目描述有一个简易内存池,内存按照大小粒度分类,每个粒度有若干个可用内存资源,用户会进行一系列内存申请,需要按需分配内存池中的资源返回申请结果成功失败列表。分配规则如下:分配的内存要大于等于内存的申请量,存在满足需求的内存就必须分配,优先分配粒度小的......
  • [1426]基于JAVA的微信公众号运营智慧管理系统的设计与实现
    毕业设计(论文)开题报告表姓名学院专业班级题目基于JAVA的微信公众号运营智慧管理系统的设计与实现指导老师(一)选题的背景和意义选题背景与意义:在当前信息化、数字化的社会环境下,微信公众号已经成为企事业单位、商家和个体进行品牌推广、客户服务、产品营销以及用户管理......
  • [1437]基于JAVA的志愿者服务智慧管理系统的设计与实现
    毕业设计(论文)开题报告表姓名学院专业班级题目基于JAVA的志愿者服务智慧管理系统的设计与实现指导老师(一)选题的背景和意义选题背景与意义:随着我国社会文明程度的不断提升,志愿服务已成为社会进步、社区建设与发展的重要力量。志愿者服务智慧管理系统作为一种信息化工具,......
  • Java的Stream流编程的排序sorted方法里参数o1,o2分别代表什么?
    先说结论:在sorted方法中,o1是最后面的元素,o2是倒数第二个元素,以此类推,流是处理元素是从后面开始取值。  packagecom.br.itwzhangzx02.learn;     importorg.junit.Test;   importjava.util.ArrayList; importjava.util.List;......
  • 实验三: JavaScript数组与函数
    实验目的熟练掌握常用JavsScript的数组、自定义函数、作用域。实验内容数组定义及元素获取;数组的遍历;数组内容的增删改查;数组的排序;数组的反转、截取、合并、元素拼接函数的声明;函数的调用;匿名函数;作用域。实验步骤:数组定义及元素获取;数组的遍历;数组内容的增删改查......
  • 面试Java岗老喜欢盯着JVM问,有那么多项目要调优吗?
    性能优化作为一个程序员,性能优化是常有的事情,不管你是刚入行的小白还是已经入坑了很久的小秃头都会经历很多不同层次的性能优化——小到代码审查大到整个系统设计的优化!大势所趋之下,如何让自己的优化方向精准到性能瓶颈的那个点以及尽可能的提高优化的性价比已经慢慢成为每一......
  • java毕业设计-基于Springboot的教学资源共享平台【代码+论文+PPT】
    全文内容包括:1、采用技术;2、系统功能;3、系统截图;4、部分代码;5、配套内容。索取方式见文末微信号,欢迎关注收藏!一、采用技术语言:Java1.8框架:Springboot数据库:MySQL5.7、8.0开发工具:IntelliJIDEA旗舰版其他:Maven3.8以上二、系统功能成绩管理:记录和追踪学生课程成绩,便于......
  • 【关注可白嫖源码】基于Java的智慧诊疗档案管理系统
     摘 要针对医院在线诊疗以及预约挂号等问题,对其进行研究分析,然后开发设计出智慧诊疗档案管理系统以解决问题。智慧诊疗档案管理系统主要功能模块包括预约挂号、取消预约、电子处方、收费查询、服务评价等,本系统采取面对对象的开发模式进行软件的开发和硬体的架设,能很好的满......