美文网首页Java
程序员修仙之路--突破内存限制的高性能排序

程序员修仙之路--突破内存限制的高性能排序

作者: 48730ba83b2d | 来源:发表于2019-03-19 17:17 被阅读5次
image.png

菜菜的涨工资申请还在待审批中…

作为一个技术人员,技术的问题还是要解决。经过线上日志的分析,日志采用小时机制,一个小时一个日志文件,同一个小时的日志文件有多个,也就是说同一时间内的日志有可能分散在多个日志文件中,这也是Y总要合并的主要原因。每个日志文件大约有500M,大约有100个。此时,如果你阅读到此文章,该怎么做呢?不如先静心想2分钟!!

问题分析
要想实现Y总的需求其实还是有几个难点的:

如何能把所有的日志文件按照时间排序
日志文件的总大小为500M*100 ,大约50G,所以全部加载到内存是不可能的
程序执行过程中,要频繁排序并查找最小元素。
那我们该怎么做呢?其中一个解决方案就是它:堆

解决方案
堆定义
堆(英语:heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质:

堆中某个节点的值总是不大于或不小于其父节点的值
堆总是一棵完全二叉树(完全二叉树要求,除了最后一层,其他层的节点个数都是满的,最后一层的节点都靠左排列)
对于每个节点的值都大于等于子树中每个节点值的堆,我们叫作“大顶堆”。对于每个节点的值都小于等于子树中每个节点值的堆,我们叫作“小顶堆”。


image.png

堆实现
完全二叉树比较适合用数组来存储(链表也可以实现)。为什么这么说呢?用数组来存储完全二叉树是非常节省存储空间的。因为我们不需要存储左右子节点的指针,单纯地通过数组的下标,就可以找到一个节点的左右子节点和父节点。


image.png
经过上图可以发现,数组位置0为空,虽然浪费了一个存储空间,但是当计算元素在数组位置的时候确非常方便:数组下标为X的元素的左子树的下标为2x,右子树的下标为2x+1。
其实实现一个堆非常简单,就是顺着元素所在的路径,向上或者向下对比然后交换位置。

添加元素
添加元素的时候我们习惯采用自下而上的调整方式来调整堆,我们在数组的最后一个空闲位置插入新元素,按照堆的下标上标原则查找到父元素对比,如果小于父元素的值(大顶堆),则互相交换。如图:


image.png

删除最大(最小元素)
对于大顶堆,堆顶的元素就是最大元素。删除该元素之后,我们需要把第二大元素提到堆顶位置。依次类推,直到把路径上的所有元素都调整完毕。


image.png

扩展阅读

小顶堆的顶部元素其实就是整个堆最小的元素,大顶堆顶部元素是整个堆的最大元素。这也是堆排序的最大优点,取最小元素或者最大元素时间复杂度为O(1)
删除元素的时候我们要注意一点,如果采用自顶向下交换元素的方式,在很多情况下造成堆严重的不平衡(左右子树深度相差较大)的情况,为了防止类似情况,我们可以把最后一个元素提到堆顶,然后调整的策略,因为最后一个元素总是在最后一级,不会造成左右子树相差很大的情况。
对于有重复元素的堆,一种解决方法是认为是谁先谁大,后进入堆的元素小于先进入堆的元素,这样在查找的时候一定要查彻底才行。另外一种方式是在堆的每个元素中存储一个链表,用来存放相同的元素,原理类似于散列表。不过这样在删除这个元素的时候需要特殊处理一下。
删除堆顶数据和往堆中插入数据的时间复杂度都是 O(logn)。
不断调整堆的过程其实就是排序过程,在某些场景下,我们可以利用堆来实现排序。


[图片上传中...(img1.png-983c5f-1552986991112-0)]

欢迎工作一到五年的Java工程师朋友们加入Java高级互联网架构:714526711

群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)
合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!

img1.png
QQ截图20190222172937.jpg

作者:菜V菜
来源:CSDN
原文:https://blog.csdn.net/weixin_43163769/article/details/88602201
版权声明:本文为博主原创文章,转载请附上博文链接!

相关文章

  • 程序员修仙之路--突破内存限制的高性能排序

    菜菜的涨工资申请还在待审批中… 作为一个技术人员,技术的问题还是要解决。经过线上日志的分析,日志采用小时机制,一个...

  • 想要开挂进阶Java架构师?这份超强(长)学习计划单 请签收

    优秀工程师的成长之路就是一条不断打怪升级之路的“修仙之路”! 而Java程序员一向比别人更难,如果说大家都在修仙的...

  • Redis的过期键删除策略和数据逐出策略

    Redis作为一个高性能的内存NoSQL数据库,其容量受到最大内存限制的限制。 在实际生产环境中使用Redis时,...

  • 蓝杯二十五

    /* 算法提高 12-2扑克排序 时间限制:1.0s 内存限制:256.0MB提交此题 问题描述扑克牌排序:构...

  • 奥运排序问题

    问题 G: 奥运排序问题 时间限制: 1 Sec 内存限制: 32 MB 题目描述 按要求,给国家进行排名。 输...

  • ACM8

    ASCII码排序 时间限制:3000 ms | 内存限制:65535 KB 难度:2 描述 输入三个字符(可以重复...

  • 八、外部排序

    八、外部排序 前面第七章介绍了内部排序需要把待排序数据全部放入内存中,然后再排序。这就限制了待排序数据的规模。当数...

  • Redis 内存淘汰与过期策略

    不管是本地缓存还是分布式缓存,为了保证较高性能,都是使用内存来保存数据,由于成本和内存限制,当存储的数据超过缓存容...

  • Redis的那些最常见面试问题

    欢迎关注公众号:程序员面试经验分享(jobbible) 1.什么是redis? Redis 是一个基于内存的高性能...

  • ACM6

    一种排序 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 现在有很多长方形,每一个长方形...

网友评论

    本文标题:程序员修仙之路--突破内存限制的高性能排序

    本文链接:https://www.haomeiwen.com/subject/nmsnmqtx.html