PriorityQueue初始化和方法

PriorityQueue概述

PriorityQueue` 是 Java 中的一个数据结构,它是一个优先队列实现,可以用来存储一组元素,并根据其优先级进行排序和检索。优先队列是一种特殊的队列,其中元素被赋予了优先级,高优先级的元素在队列中排在低优先级元素的前面。

以下是 PriorityQueue 的一些重要特性和用法:

  1. 基本特性

    • PriorityQueue 是一个基于堆(heap)数据结构实现的,通常是一个最小堆(Min Heap),也可以通过传递比较器来创建最大堆(Max Heap)。
    • 元素根据其优先级自动排序,高优先级的元素在队列前面。
  2. 元素插入

    • 使用 add()offer() 方法将元素插入队列中。
  3. 元素获取

    • 使用 peek() 方法可以获取队列中优先级最高的元素,但不删除它。
    • 使用 poll() 方法可以获取并移除队列中优先级最高的元素。
  4. 遍历元素

    • PriorityQueue 并没有提供迭代器来遍历元素,因为它并不保证元素的顺序。
  5. 自定义优先级

    • 可以通过为构造函数传递自定义的 Comparator 对象来定义元素的优先级比较规则。如果不提供比较器,元素必须实现 Comparable 接口来自然排序。
  6. 线程安全性

    • PriorityQueue 不是线程安全的,如果多个线程同时访问一个 PriorityQueue 实例,需要进行外部同步处理。
  7. 应用场景

    • PriorityQueue 常用于一些需要按优先级处理任务的场景,如任务调度器、最短路径算法(如Dijkstra算法)等。

以下是一个示例,演示了如何创建和使用 PriorityQueue

import java.util.PriorityQueue;

public class PriorityQueueExample {
    public static void main(String[] args) {
        // 创建一个最小堆的PriorityQueue
        PriorityQueue<Integer> minHeap = new PriorityQueue<>();
        
        // 插入元素
        minHeap.add(5);
        minHeap.add(2);
        minHeap.add(8);
        
        // 获取并移除最小元素
        int smallest = minHeap.poll(); // 结果:2
        System.out.println("Smallest element: " + smallest);
        
        // 获取但不移除最小元素
        int smallestPeek = minHeap.peek(); // 结果:5
        System.out.println("Smallest element (peek): " + smallestPeek);
    }
}

使用比较器构造最大堆

PriorityQueue<ListNode> q = new PriorityQueue<>(lists.length, (a, b) -> a.val - b.val);

这里使用<>来指定元素类型,确保a和b能够正确地识别为ListNode类型,从而访问val属性。
需要注意初始容量不能是0,加入的元素也不能是null

// 使用 Lambda 表达式创建最大堆比较器
Comparator maxHeapComparator = (a, b) -> b - a;
PriorityQueue maxHeap = new PriorityQueue<>(maxHeapComparator);
Comparator 是一个函数式接口,它只包含一个抽象方法 compare(T o1, T o2),这个方法接受两个参数并返回一个整数,用于比较这两个对象的大小。由于 Comparator 是函数式接口,因此可以使用 Lambda 表达式来创建它的实例。

在上述代码中,(a, b) -> b.val - a.val 是一个 Lambda 表达式,它实际上是一个匿名函数,等价于以下的 compare 方法:

int compare(ListNode a, ListNode b) {
    return b.val - a.val;
}

Lambda 表达式的左侧 (a, b) 是参数列表,右侧 b.val - a.val 是函数体,表示通过比较 b.vala.val 的差值来确定两个对象的顺序。这个差值为正时,表示 ba 大,为负时,表示 ab 大,为零时,表示它们相等。

因此,Lambda 表达式 (a, b) -> b.val - a.val 是创建了一个比较器,用于按照 ListNode 对象的 val 属性从大到小排序。这个比较器可以传递给 PriorityQueue,以确保最大的节点在堆的顶部。Lambda 表达式的简洁性使得它成为创建匿名函数对象的一种便捷方式。

扩容机制

在 PriorityQueue 中,动态扩容是在插入元素时进行的。以下是动态扩容的一般细节:

初始化:创建一个初始容量(默认是11)的数组,并将第一个元素插入其中。

插入元素:当插入一个新元素时,首先将其添加到数组的末尾。然后,它会根据堆的性质,比较新元素和其父节点的值。如果满足堆的性质,操作结束。如果不满足,就将新元素和父节点交换位置,然后继续比较新元素和新的父节点,直到满足堆的性质为止。

数组扩容:如果在插入元素时发现数组已满,就需要进行扩容。扩容通常会创建一个更大的新数组,然后将所有元素从旧数组复制到新数组中。

扩容策略:通常情况下,扩容的策略是将数组的容量翻倍,以减少频繁扩容的次数。这样可以保持在插入大量元素时的高效性能。

需要注意的是,虽然 PriorityQueue 具有动态扩容的机制,但扩容操作的代价相对较高,因为需要复制数组的所有元素。因此,在处理大量数据时,建议初始化 PriorityQueue 时指定一个足够大的初始容量,以减少扩容的次数,提高性能。

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在引用中,我们看到了一个初始化priority_queue的例子。其中,priority_queue是一个优先队列,使用了自定义的Node类型作为元素类型,使用了vector作为底层容器,并且使用了Cmp作为比较函数。具体的代码如下所示: priority_queue<Node, vector<Node>, Cmp> priorityQueue; 在引用中,我们看到了另一个初始化priority_queue的例子。其中,priority_queue是一个优先队列,使用了默认的less<T>比较函数来比较元素大小。具体的代码如下所示: int main() { priority_queue<Node> priorityQueue; for (int i = 0; i < 5; i++) { priorityQueue.push(Node{i, 5 - i}); } while (!priorityQueue.empty()) { Node top = priorityQueue.top(); cout << "size:" << top.size << " price:" << top.price << endl; priorityQueue.pop(); } return 0; } 在引用中,提到了如果需要使用greater<Node>来初始化priority_queue,还需要对Node的>符号进行重载。这里并没有给出具体的代码示例。 综上所述,初始化priority_queue的方式可以根据实际需求来选择使用自定义的比较函数或者使用默认的比较函数。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [算法日记(九)之优先队列](https://blog.csdn.net/m0_63932570/article/details/125020628)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值