剑指offer面试题40 最小k个数:https://www.cnblogs.com/guoyu1/p/12164785.html
剑指offer面试题41 数据流中的中位数:https://www.cnblogs.com/guoyu1/p/12274753.html
1、优先队列的基本概念:
在说明优先队列之前,先回顾普通队列,普通队列就是先插入的元素,先出队。
优先队列和普通队列相比,允许元素插入后,并不按照插入的顺序弹出,而是按照优先级的顺序进行弹出,一般是先弹出最小元素。
2、优先队列的基本操作:
insert(插入)
deleteMin(删除最小者):找到、返回、删除优先队列中的最小元素。
3、优先队列的实现:
优先队列有三种实现方式,分别是,正常数组、排序数组、二叉堆。其时间复杂度如下图

(1)顺序数组实现:每次插入元素,都要对进行排序,删除元素只需要拿出数组第一个元素即可。时间复杂度:入队O(n),出队O(1)
import javax.swing.plaf.synth.SynthOptionPaneUI;
public class PriorityQueue {
private int[] arr;
//优先队列的长度,用于初始化数组
private int Queuesize;
//记录当前优先队列中存储的元素的个数,因为数组已经初始化长度就固定了,
// 无法用.length方法去判断当前队列存了几个元素
private int itemNum;
//构造方法,给队列赋初始值
public PriorityQueue(int size) {
this.Queuesize = size;
this.itemNum = 0;
this.arr = new int[size];
}
//元素出队
public int deleteMin() {
int result;
if (isEmpty()) {
result = -1;
System.out.println("队列为空,没有元素");
} else {
//队列非空,返回第一个元素,并删除
result = arr[0];
for (int i = 0; i < itemNum - 1; i++) {
arr[i] = arr[i + 1];
}
itemNum--;
}
return result;
}
//元素入队
public void insert(int value) {
//元素入队前先要检查优先队列是否已满
if (isFull()) {
//如果优先队列满了,就直接返回,不能插入
System.out.println("优先队列已满");
} else {
//优先队列没有满,分两种情况:空队列,已有元素队列
if (itemNum == 0) {
//空队列,直接添加元素即可
arr[0]=value;
itemNum++;
} else {
//提前定义
int i;
//非空队列,对数组进行排序,从小到大排序,{1,2,3,5,6,7,0,0,0},插入元素4
for (i = itemNum - 1; i >= 0; i--) {
if (value < arr[i]) {
//如果发现value的值比队列已存元素小,说明当前值应该插入到已存元素之前,
// 因此,将arr[i]后的元素移位,{1,2,3,5,6,7,7,0,0}
arr[i + 1] = arr[i];
} else {
//比已存元素大,说明找对位置了{1,2,3,5,5,6,7,0,0}
//此时要停止循环,不然所有比value小的元素都被操作了
break;
}
}
arr[i + 1] = value;
itemNum++;
}
}
}
//检查优先队列已满方法
public Boolean isFull() {
return (itemNum == Queuesize);
}
//检查队列为空方法
public Boolean isEmpty() {
return (itemNum == 0);
}
public void display() {
if(itemNum==0){
System.out.println("空队列");
}else{
for (int i = 0; i < itemNum; i++) {
System.out.print(arr[i]+" ");
}
System.out.println();
}
}
//测试队列是否正确
public static void main(String[] args) {
PriorityQueue p = new PriorityQueue(5);
p.insert(1);
p.insert(2);
p.insert(7);
p.insert(5);
p.insert(4);
p.display();
p.insert(8);
p.display();
for (int i=0;i<6;i++){
int value=p.deleteMin();
System.out.println("出队元素"+value);
}
p.display();
}
}
(2)二叉堆实现://TODO
4、Java API
import java.util.PriorityQueue;import java.util.Comparator;PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(k, new Comparator<Integer>() {
@Override public int compare(Integer o1, Integer o2) { return o2.compareTo(o1); } });
peek()//返回队首元素 poll()//返回队首元素,队首元素出队列 add()//添加元素 size()//返回队列元素个数 isEmpty()//判断队列是否为空,为空返回true,不空返回false
PriorityQueue的常用方法有:poll(),offer(Object),size(),peek()等。
- 插入方法(offer()、poll()、remove() 、add() 方法)时间复杂度为O(log(n)) ;
- remove(Object) 和 contains(Object) 时间复杂度为O(n);
- 检索方法(peek、element 和 size)时间复杂度为常量。