1、堆
->堆总是一棵完全二叉树
-> 堆中某个节点的值总是不大于或不小于其父节点的值
->堆的所有元素按照顺序存储的方式存储在一维数组中
-> 大根堆【根节点最大】;小根堆【根节点最小】
-> 堆是一棵完全二叉树,因此可以采用层序规则来顺序存储数值。
![](https://i-blog.csdnimg.cn/blog_migrate/9ec2cce99b81bc76cc1434a51f3db721.png)
-> 对于非完全二叉树,不适合用顺序存储的方式。因为会有空间的浪费,导致空间利用率比较低。
2、堆的创建
![](https://i-blog.csdnimg.cn/blog_migrate/54d7f3b3a2b4a5d64cdeb93565f66d62.png)
上边所示二叉树不满足大根堆或者小根堆,所以需要进行调整。
以大根堆为例:【从下边开始】调整后的树:
![](https://i-blog.csdnimg.cn/blog_migrate/1b2371c2cc719ba10ad96fb04d33b4ea.png)
2-1 建立大根堆
思想:从每棵子树的根节点开始向下调整;对于建大根堆,需要从最下边的子树开始进行调整;
-> 如何确定最后一棵子树根节点的位置:(len-1-1)/2(数组长度为len)
->如何确定下一个根节点的位置:当前根节点的下标-1
->如何调整:每棵子树均实现向下调整
2-2建立大根堆----代码实现
![](https://i-blog.csdnimg.cn/blog_migrate/b70a063a0729a299a5d5d95ba031e0c8.png)
![](https://i-blog.csdnimg.cn/blog_migrate/98935c3465e4f7526624b4a9ff43e6b4.png)
3、堆的插入与删除
3-1堆的插入
思想:step1.将要插入的数据先放在该数组最后一个位置【不是数组长度的最后一个,而是usedSize】;
step2.将插入的该数据与每棵子树的根节点比较,(建立大根堆),如果该节点值比其父结点的值大,就向上调整,直到孩子节点下标为0;
![](https://i-blog.csdnimg.cn/blog_migrate/17a6e05b4148335f753d1bd9cbe5b6a4.png)
![](https://i-blog.csdnimg.cn/blog_migrate/8aed03554dfa049c84e12ea30bf92b5d.png)
3-1堆的删除
思想:step1.将堆顶元素与最后一个位置元素交换,此时usedSize-1【不是数组长度的最后一个,而是usedSize】;
step2.交换完之后,从0节点开始向下调整即可
![](https://i-blog.csdnimg.cn/blog_migrate/1fef3a137bcea8c437a19df52d0ad66f.png)
4、常用接口介绍
4-1 PriorityQueue
-> PriorityQueue线程不安全,PriorityBlockingQueue是线程安全的;
->不能插入null对象
->优先级队列中放的必须是能够比较大小的对象
->插入和删除元素的时间复杂度:O(log2(N))
->优先级队列没有容量限制,其内部可以自动扩容,可以插入任意多个元素
->优先级队列底层使用了堆数据结构
->目前自己所用的编辑器对于PriorityQueue来说是小堆,如果需要大堆,则需要用户提供比较器。【实现Comparator接口,然后重写该接口中的compare方法即可】
4-2 插入/删除/获取优先级最高的元素
boolean offer(E e):插入元素e,插入成功返回true;不能插入空对象;空间不够时会自动扩容;
E peek():获取优先级最高的元素;如果优先级队列为空,返回null
E poll(): 删除优先级最高的元素并返回
boolean isEmpty():检测优先级队列是否为空,空则返回true
5、堆的典型应用
1、找前k个最大的值
把元素全部放到大根堆里头;最大值即为堆顶元素,弹出K次就可拿到前K个最大值。
eg:
![](https://i-blog.csdnimg.cn/blog_migrate/698910b278bf86e5ac521e3f7fbff522.png)
2、上面代码实现的时间复杂度为O(NlogN);
下面实现的为O(logN);
思想:获取前K个最大---->建立小根堆
获取前K个最小---->建立大根堆【如下】
![](https://i-blog.csdnimg.cn/blog_migrate/4ea59ab2968ab781cba57949fe7f3de0.png)
3、堆排序
从小到大排序---->建立大根堆
从大到小排序---->建立小根堆
具体操作如下:
![](https://i-blog.csdnimg.cn/blog_migrate/eeeddac4ce6b373cd15fef612abe23cc.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d0b1b31d1082e8c391ad9ed561b331f6.png)