优先队列(堆)
剑指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)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | 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)时间复杂度为常量。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)