目录
3堆的存储方式???????
//创建堆
public void creatHeap(){
int preheap;//每次的根节点
for ( preheap=(usesize-1-1)/2;preheap>=0;preheap--){
signHeap(preheap,usesize);
}
}
//向下调整为大根堆为例
private void signHeap(int preheap,int end){//向下调整
int child=preheap*2+1;//preheap左子树下标
while (child<end){
if(child+1<end&&elem[child]<elem[child+1])child++;
//现在child指向孩子节点的最大值
if (elem[preheap]<elem[child]){
swap(preheap,child);
preheap=child;
child=child*2+1;
}
else break;
}
}
private void swap(int i,int j) {
int tmp = elem[i];
elem[i] = elem[j];
elem[j] = tmp;
}
堆的插入总共需要两个步骤:
1. 先将元素放入到底层空间中(注意:空间不够时需要扩容)
2. 将最后新插入的节点向上调整,直到满足堆的性质
public void offer(int key){
if(isFull()) Arrays.copyOf(elem,elem.length*2);//扩容
elem[usesize]=key;
usesize++;
//调整为大根堆,向上调整
siftUp(usesize-1);
}
//向上调整
private void siftUp(int child) {
int parent = (child-1)/2;
while (child > 0) {//或者parent>0
if(elem[child] > elem[parent]) {
swap(child,parent);
child = parent;
parent = (child-1)/2;
}else {
break;
}
}
}
1. 将堆顶元素对堆中最后一个元素交换
2. 将堆中有效数据个数减少一个
3. 对堆顶元素进行向下调整
public int poll() {
int tmp = elem[0];
swap(0,usesize-1);
usesize--;
signHeap(0,usesize);//0下标元素和最后一个元素换,之后只有0下标还不是大根堆,调整
return tmp;
}
1. 使用时必须导入PriorityQueue所在的包,即:import java.util.PriorityQueue;
2. PriorityQueue中放置的元素必须要能够比较大小,不能插入无法比较大小的对象,否则会抛出
ClassCastException异常(放入自定义元素类可以让该类继承Comparable并重写ComparTo方法,或者写比较器)例:
class Imp implements Comparator<Integer>{
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);//大根堆
}
}
public class Test1 {
public int[] smallestK(int[] arr, int k) {
//堆的默认比较时小根堆,我们建立大根堆需要比较器
PriorityQueue<Integer> p=new PriorityQueue<Integer>(new Imp());
3. 不能插入null对象,否则会抛出NullPointerException
4. 没有容量限制,可以插入任意多个元素,其内部可以自动扩容
5. 插入和删除元素的时间复杂度为
6. PriorityQueue底层使用了堆数据结构
7. PriorityQueue默认情况下是小堆---即每次获取到的元素都是最小的元素
见下一篇博客,介绍所有排序