构造优先队列我们需要引入一个堆的该概念
堆
堆在逻辑上一个完全二叉树
堆在物理上是一个数组
满足任意结点的值都大于其子树中结点的值,叫做大堆,或者大根堆,或者大堆 ; 反之,则是小堆,或者小根堆,或者小堆。
堆的基本作用是,快速找集合中的最大值或者最小值
建堆是根据向上调整,和向下调整同时完成的
我们所建的堆未考虑扩容,建堆的代码为大堆代码。
public class MyPriorityQueue {
private int[] array = new int[100];
private int size = 0;
public void offer( int x) {
this.array[this.size] = x;
this.size++;
shiftUp(this.array,this.size,this.size-1);
}
//向上调整,构成大堆
private void shiftUp(int[] array, int size, int index) {
int child = index;
int parent = (child - 1) / 2;
while(child > 0) {
if(array[parent] < array[child]) {
int tmp = array[parent];
array[parent] = array[child];
array[child] = tmp;
} else {
break;
}
child = parent;
parent = (child - 1) / 2;
}
}
public Integer poll() {
if(this.size <= 0) {
return null;
}
int ret = this.array[0];
this.array[0] = array[this.size - 1];
this.size--;
shiftDown(this.array,this.size,0);
return ret;
}
public boolean isEmpty() {
return this.size == 0;
}
//向下调整,构成大堆
//调整一次,为堆的输出做准备
private void shiftDown(int[] array,int size,int index) {
int parent = index;
int child = (parent * 2) + 1;
while(child < size) {
if(child + 1 < size && array[child + 1] > array[child]) {
child = child + 1;
}
if(array[child] > array[parent]) {
int tmp = array[parent];
array[parent] = array[child];
array[child] = tmp;
} else {
break;
}
parent = child;
child = (parent * 2) + 1;
}
}
public static void main(String[] args) {
MyPriorityQueue myPriorityQueue = new MyPriorityQueue();
myPriorityQueue.offer(7);
myPriorityQueue.offer(9);
myPriorityQueue.offer(8);
myPriorityQueue.offer(4);
myPriorityQueue.offer(6);
myPriorityQueue.offer(5);
while(!myPriorityQueue.isEmpty()) {
Integer cur = myPriorityQueue.poll();
System.out.print(cur + " ");
}
}
}
而在Java这个库中,优先队列是小堆
我们若是想把小堆变成大堆,有以下几种方法
构建一个类,使用Comparator接口,重写方法compare,并且引入到优先队列中。
import java.util.Comparator;
import java.util.PriorityQueue;
public class TestPriorityQueue {
static class A implements Comparator<Integer> {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
}
public static void main(String[] args) {
PriorityQueue<Integer> pQ = new PriorityQueue<>(new A());
pQ.offer(4);
pQ.offer(1);
pQ.offer(5);
pQ.offer(7);
pQ.offer(8);
while(!pQ.isEmpty()) {
System.out.print(pQ.poll() + " ");
}
}
}
第二种
直接在优先对列中重写compare方法
import java.util.Comparator;
import java.util.PriorityQueue;
public class TestPriorityQueueTwo {
public static void main(String[] args) {
PriorityQueue<Integer> pQ = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
pQ.offer(5);
pQ.offer(3);
pQ.offer(7);
pQ.offer(0);
pQ.offer(2);
while (!pQ.isEmpty()) {
System.out.print(pQ.poll() + " ");
}
}
}
第三种就是在第二种的基础上更加简化
,异曲同工。
import java.util.PriorityQueue;
public class TestPriorityQueueThree {
public static void main(String[] args) {
PriorityQueue<Integer> pQ = new PriorityQueue<>((Integer o1,Integer o2) -> {
return o2 - o1;
});
PriorityQueue<Integer> pQ1 = new PriorityQueue<>((Integer o1,Integer o2) -> o2 - o1);
PriorityQueue<Integer> pQ2 = new PriorityQueue<>((o1,o2) -> o2 - o1);
}
}