优先队列(堆)

剑指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)时间复杂度为常量。
posted @   guoyu1  阅读(527)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示