剑指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)时间复杂度为常量。