优先队列PriorityQueue实现 大小根堆 解决top k 问题
转载:https://www.cnblogs.com/lifegoesonitself/p/3391741.html
PriorityQueue是从JDK1.5开始提供的新的数据结构接口,它是一种基于优先级堆的极大优先级队列。优先级队列是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优先权的元素。如果不提供Comparator的话,优先队列中元素默认按自然顺序排列,也就是数字默认是小的在队列头,字符串则按字典序排列(参阅 Comparable),也可以根据 Comparator 来指定,这取决于使用哪种构造方法。优先级队列不允许 null 元素。依靠自然排序的优先级队列还不允许插入不可比较的对象(这样做可能导致 ClassCastException)
此队列的头是按指定排序方式的最小元素。如果多个元素都是最小值,则头是其中一个元素——选择方法是任意的。
队列检索操作 poll、remove、peek 和 element 访问处于队列头的元素。
优先级队列是无界的,但是有一个内部容量,控制着用于存储队列元素的数组的大小。
它总是至少与队列的大小相同。随着不断向优先级队列添加元素,其容量会自动增加。无需指定容量增加策略的细节。
注意1:该队列是用数组实现,但是数组大小可以动态增加,容量无限。
注意2:此实现不是同步的。不是线程安全的。如果多个线程中的任意线程从结构上修改了列表, 则这些线程不应同时访问 PriorityQueue 实例,这时请使用线程安全的PriorityBlockingQueue 类。
注意3:不允许使用 null 元素。
注意4:此实现为插入方法(offer、poll、remove() 和 add 方法)提供 O(log(n)) 时间;
为 remove(Object) 和 contains(Object) 方法提供线性时间;
为检索方法(peek、element 和 size)提供固定时间。
注意5:方法iterator()中提供的迭代器并不保证以有序的方式遍历优先级队列中的元素。
至于原因可参考下面关于PriorityQueue的内部实现
如果需要按顺序遍历,请考虑使用 Arrays.sort(pq.toArray())。
注意6:可以在构造函数中指定如何排序。如:
PriorityQueue()
使用默认的初始容量(11)创建一个 PriorityQueue,并根据其自然顺序来排序其元素(使用 Comparable)。
PriorityQueue(int initialCapacity)
使用指定的初始容量创建一个 PriorityQueue,并根据其自然顺序来排序其元素(使用 Comparable)。
PriorityQueue(int initialCapacity, Comparator comparator)
使用指定的初始容量创建一个 PriorityQueue,并根据指定的比较器comparator来排序其元素。
注意7:此类及其迭代器实现了 Collection 和 Iterator 接口的所有可选 方法。
PriorityQueue的内部实现
PriorityQueue对元素采用的是堆排序,头是按指定排序方式的最小元素。堆排序只能保证根是最大(最小),整个堆并不是有序的。
方法iterator()中提供的迭代器可能只是对整个数组的依次遍历。也就只能保证数组的第一个元素是最小的。
package com.chenshuyi.data; import java.util.Comparator;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Random; //固定容量的优先队列,模拟大顶堆,用于解决求topN小或 topk大的问题
@SuppressWarnings({ "unchecked", "rawtypes" })
public class TopKwithPriorityQueue<E extends Comparable> {
private PriorityQueue<E> queue;
private int K; // 堆的最大容量,即 topk,所以maxsize=k public TopKwithPriorityQueue(int maxSize) {
if (maxSize <= 0)
throw new IllegalArgumentException();
this.K = maxSize;
this.queue = new PriorityQueue(maxSize, new Comparator<E>() {
public int compare(E o1, E o2) {
return o1.compareTo(o2);
// 生成最大堆使用o2-o1,生成最小堆使用o1-o2, 并修改 e.compareTo(peek) 比较规则return (o2.compareTo(o1));
}
});
} public void add(E e) {
if (queue.size() < K) { // 未达到最大容量,直接添加
queue.add(e);
} else { // 队列已满
E peek = queue.peek(); // 取堆顶元素
if (e.compareTo(peek) > 0) { // 将新元素与当前堆顶元素比较,保留较小的元素
queue.poll();
queue.add(e);
}
}
} // public List<E> sortedList() {
// List<E> list = new ArrayList<E>(queue); // 可以将整个优先队列传入 arraylist的构造方法做参数
// Collections.sort(list); // PriorityQueue本身的遍历是无序的,最终需要对队列中的元素进行排序
// return list;
// } public static void main(String[] args) {
final TopKwithPriorityQueue pq = new TopKwithPriorityQueue(3); // 返回前k=10位
Random random = new Random();
int rNum = 0;
System.out.println("100 个 0~999 之间的随机数:-----------------------------------");
for (int i = 1; i <= 20; i++) {
rNum = random.nextInt(1000);
System.out.print(rNum + ",");
pq.add(rNum);
}
System.out.println("\n PriorityQueue 本身的遍历是无序的:返回的top10 最小堆是:-----------------------------------");
Iterable<Integer> iter = new Iterable<Integer>() {
public Iterator<Integer> iterator() {
return pq.queue.iterator();
}
};
for (Integer item : iter) {
System.out.print(item + ",");
}
System.out.println();
System.out.println("PriorityQueue 排序后的遍历:返回的top10 最小堆是:-----------------------------------");
/*
* for (Integer item : pq.sortedList()) { System.out.println(item); }
*/
// 或者直接用内置的 poll() 方法,每次取队首元素(堆顶的最大值)
while (!pq.queue.isEmpty()) {
System.out.print(pq.queue.poll() + ", ");
}
}
}
由于仅仅保存了K个数据,有调整最小堆的时间复杂度为O(lnK),因此TOp K算法(问题)时间复杂度为O(nlnK)
堆排序算法的性能分析:
空间复杂度:o(1);
堆调整一次的时间复杂度是O(logK)。所以,通过堆来解决top K 问题的时间复杂度是O(nlogK).
其中,n为数据的个数,K为堆维护的数据的个数。
稳定性:不稳定
优先队列PriorityQueue实现 大小根堆 解决top k 问题的更多相关文章
- 优先队列实现 大小根堆 解决top k 问题
摘于:http://my.oschina.net/leejun2005/blog/135085 目录:[ - ] 1.认识 PriorityQueue 2.应用:求 Top K 大/小 的元素 3 ...
- PriorityQueue实现大顶堆
在做一道算法时需要使用大顶堆,所以查了一下记录. 使用PriorityQueue实现大顶堆 PriorityQueue默认是一个小顶堆,然而可以通过传入自定义的Comparator函数来实现大顶堆.如 ...
- scala写算法-用小根堆解决topK
topK问题是指从大量数据中获取最大(或最小)的k个数,比如从全校学生中寻找成绩最高的500名学生等等. 本问题可采用小根堆解决.思路是先把源数据中的前k个数放入堆中,然后构建堆,使其保持堆序(可以简 ...
- 随手练——HDU Safe Or Unsafe (小根堆解决哈夫曼问题)
HDU 2527 :http://acm.hdu.edu.cn/showproblem.php?pid=2527 哈夫曼树,学完就忘得差不多了,题目的意思都没看懂,有时间复习下,看了别人的才知道是怎么 ...
- 大数据热点问题TOP K
1单节点上的topK (1)批量数据 数据结构:HashMap, PriorityQueue 步骤:(1)数据预处理:遍历整个数据集,hash表记录词频 (2)构建最小堆:最小堆只存k个数据. 时间复 ...
- 现有n 个乱序数,都大于 1000 ,让取排行榜前十,时间复杂度为o(n), top10, 或者 topK,应用场景榜单Top:10,堆实现Top k
一.topK python实现 def topk(k, lst): top = [0 for i in range(k)] #生成一个长度为K 的有序列表 for item in lst: #循环 ...
- 使用堆实现Top K 算法 JS 实现
1. 堆算法Top,时间复杂度 O(LogN) function top(arr,comp){ if(arr.length == 0){return ;} var i = arr.length / 2 ...
- Top K问题的两种解决思路
Top K问题在数据分析中非常普遍的一个问题(在面试中也经常被问到),比如: 从20亿个数字的文本中,找出最大的前100个. 解决Top K问题有两种思路, 最直观:小顶堆(大顶堆 -> 最小1 ...
- 【Java源码】集合类-优先队列PriorityQueue
一.类继承关系 public class PriorityQueue<E> extends AbstractQueue<E> implements java.io.Serial ...
随机推荐
- oracle连接池问题
1.数据来源. 控制台地址:172.30.252.164:7001/console 登陆: weblogic/weblogic#123数据库jdbc:oracle:thin:@172.30.252.1 ...
- cocos2d-x 3.3 引用【#include "cocos-ext.h"】头文件出现编译错误
添加[#include "cocos-ext.h"] 头文件后报错 f:\projects\test_httpclient\cocos2d\extensions\gui\cccon ...
- ansible一些基本操作
一.介绍 特性 (1).no agents:不需要在被管控主机上安装任何客户端: (2).no server:无服务器端,使用时直接运行命令即可: (3).modules in any languag ...
- 20145215《Java程序设计》第二周学习总结
教材内容总结 类型.变量与运算符 *基本类型 整数(short.int.long) 字节(byte) 浮点数(float/double) 字符(char)将一个数字字母或者符号用单引号标识,字符串用双 ...
- 20135302魏静静——linux课程第四周实验及总结
linux课程第四周实验及总结 一.实验 我选择的是第20号系统调用,getpid 代码如下: /* getpid.c */ #include <unistd.h> #include &l ...
- 怎样让.bat文件直接运行不需要右键管理员权限
:: BatchGotAdmin :------------------------------------- REM --> Check for permissions >nul 2&g ...
- getJson同步
$.ajaxSettings.async = false;//在执行之前加$.ajaxSettings.async = false; (同步执行) function get_no_order_ar ...
- 在linux上使用tomcat服务器图片验证码不显示问题
背景描述:在liunx系统上,使用tomcat中间件,访问web项目,登录页面的图片验证码显示不出来,但是在window系统上可以正常显示 解决方案:设置一下这个文件tomcat/bin/catali ...
- MySQL INSERT语句
insert的语法 INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE] [INTO] tbl_name [(col_name,...)] ...
- [ACM]51nod 贪心专题
目录 A 低买高卖 C 接水问题 D做任务一 E做任务三 51nod一个贪心专题,大多数都是见过的套路,做题找找感觉,有些题解思路懒得写了,直接贴毕姥爷的直播题解了 A 低买高卖 考虑股票市场,一共有 ...