知识补充
小根堆:每个节点的值小于其左右孩子节点的值
大根堆:每个节点的值大于其左右孩子节点的值
根据源码可知,优先级队列底层使用数组存储数据,而数据结构是基于堆(默认小根堆)实现的。
优先级队列中最核心的方法就是插入/删除/获取操作
PriorityQueue优先级队列
特点: 底层数据结构是堆(默认小根堆)
①不可添加null值 ②数据可以重复 ③其内数据按小根堆形式
- 以下基于小根堆简单自定义实现优先级队列
1.add()操作
基本思路:
①每次都将value插入数组有效末尾位置index,找到它的父节点
②若value值小于父节点值,从上往下 进行调整 ,将原来的父节点与value交换,并更新index值,继续向上比较直至调整到0号下标,若仍然小于更新后父节点的值,继续向上调整并重新赋值
③向上调整后,将value放置在index位置
public void add(T value){
if(table.length==size){
int newCap=table.length<<1;//新数组容量
table= Arrays.copyOf(table,newCap);
}
if(size==0){
table[0]=value;
}else {
//每次都将元素插入最后有效位置,即size位置为插入的位置
siftUp(size,value);
}
size++;
}
//向上调整
private void siftUp(int index,T value){
while(index>0){
int parent = (index - 1) >> 1;//找父节点位置
if (value.compareTo(table[parent]) < 0) {
table[index]=table[parent];
index=parent;
}else{
break;
}
}
table[index] = value;
}
2.poll()操作
基本思路: 首先明确poll()操作要删除的元素的最小值,即0号下标元素
①将数组中的最小元素与最后一个元素交换,将最后一个元素置空即完成删除操作
②对数据 从上往下 进行调整,使其仍然满足小根堆形式:
从0号下标开始遍历 所有非叶子节点元素 ,将其左右孩子节点中的最小值与父节点进行比较,若小于则将最小值放在父节点的位置,继续向下调整。
③向下调整后,将value值放在index位置
public T poll(){
if(size==0)
return null;
T oldValue=table[0];
T value=table[size-1];
table[size-1]=null;
size--;
siftDown(0,value);
return oldValue;
}
//向下调整
private void siftDown(int index,T value){
int half=size>>1;//访问所有非叶子节点
while(index < half) {
int child = 2 * index + 1;//左孩子
int right = child + 1;
//找到左、右孩子最小值
if (right < size && table[child].compareTo(table[right]) > 0) {
child = right;//child中存储左右孩子最小值
}
if (table[child].compareTo(value) < 0) {
//最小孩子节点小于父节点
table[index] = table[child];
index = child;
} else {
break;
}
}
table[index] = value;
}
3.peek()操作
peek()获取的是数组元素最小值
public T peek(){
return (size == 0) ? null : (T) table[0];
}
测试
public static void main(String[] args) {
DIYPriorityQueue<Integer> queue = new DIYPriorityQueue<>();
queue.add(23);
queue.add(45);
queue.add(13);
queue.add(99);
queue.add(34);
queue.add(5);
queue.add(3);
System.out.println(">>>输出队列>>>");
queue.toString();
System.out.println();
System.out.println("执行第一次删除得到的元素:"+queue.poll());
System.out.println("执行第二次删除得到的元素:"+queue.poll());
System.out.println(">>>现在的队列>>>");
queue.toString();
}
运行结果如下:
由以上自定义实现可知,优先级队列PriorityQueue可以实现数据由大到小排序:poll操作获得的元素即为数据中的最小值