✨hello,愿意点进来的小伙伴们,你们好呐!
✨ 系列专栏:【数据结构】
本篇内容:手撕 PriorityQueue 源码
作者简介:一名现大二的三非编程小白
我们创建一个Person类,类中有age成员变量。
创建PriorityQueue 对象,且往其中存放Person对象,来看看原码中是如何实现的
1.我们先创建一个PriorityQueue对象,来看一下底层是如何创建的。
2.可以看到PriorityQueue无参构造器在源码中会调用另一个构造器,传入一个整型与comparator对象,该整型是我们首次创建数组的大小。
3.我们可以看到在调用的构造器中,判断数组首次创建的大小是否大于1,否则抛异常,然后创建一个Object数组赋给quque,将 null赋给 comparator
这时候创建对象的代码完毕,最终结果在内存中创建了一个容量为11的Object数组
第一次offer比较特殊,因为在之前堆中是没有对象的,那么第一次给堆添加对象会发生什么呢?接下来让我们来瞧瞧
2. 再来取出堆中的元素的个数,去判断是否堆已经满,满则扩容
3. 最后再来判断是否是存储进堆第一个对象,很明细我们现在要存进去的是堆第一个对象,所以进入if语句中
目前为止,添加第一个对象完毕,接下来我们来看看添加第二次对象会有什么变化呢?
1.第二次offer时,会进入 siftUp 方法中。我们来看看该方法中会以什么方式来创建呢?
2. 在该方法中,因为创建PriorityQueue时并没有传入Comparator,所以会进入else语句中
3. k 是 原本对象应该存进堆中的位置,x是要存入的对象
4. 我们会看到在该方法会将所存入的对象强制转化成Comparable,所以我们得知在该情况下想要往堆中存放对象的时候,该对象类型要实现Comparable接口,但是Person并没有实现该接口,那么我们先来实现该接口再来继续往下看。
最后在下面代码中去给堆添加对象,并调节堆。
我们可以看到目前的堆是小根堆,那么我们要怎么样才可以将小根堆调整为大根堆呢?
其实很简单,只要我们调整Person类中的compareTo的返回值即可。
在siftUpComparable中的if判断中就可以体现出
上面我们找到了自定义类型的添加入堆中源码的解析,自定义类型添加入堆,必须实现Comparable接口才可以进行判断,那么现在我们会有一个疑问,那么要是存入的类型是Integer类型的元素呢?Integer中有继承Comparable接口与重写compareTo,那么会有一个判断的规则,所以有固定的大小根堆,但是我们怎么来将它的根堆转换呢?
在该逻辑下,默认会将Integer类型的数据调整为小根堆。但是我们要怎么将其该成大根堆呢?
这时候,就要来认识一下 PriorityQueue中的另一个构造器
1. 在该构造器中调用第一个构造器并传入参数。
2.在该构造器中,对comparator比较器赋值
认识了这个构造器后,我们应该怎么来传参呢?
我们可以在创建PriorityQueue对象时传入匿名内部类Comparator,并重写compare方法。
关于PriorityQueue的源码就介绍到这里,欢迎大佬们指点