TOP-K问题
程序员文章站
2024-03-15 21:52:06
...
其实这个>其实我是一个算法渣,也不怎么会算法,只是最近遇到这个问题,就顺手谷歌一下,遇到一个不错的解法,记录一下
修改部分代码就可以获取最大堆 和 最小堆,参考了这篇文章基于堆实现的优先级队列:PriorityQueue 解决 Top K 问题
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Random;
/**
* 指定元素数量的最大堆
* @author Think
*
* @param <E>
*/
public class FixSizedPriorityQueue <E extends Comparable<E>> implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private PriorityQueue<E> queue;
private int maxSize; // 堆的最大容量
public FixSizedPriorityQueue(int maxSize) {
if (maxSize <= 0)
throw new IllegalArgumentException();
this.maxSize = maxSize;
this.queue = new PriorityQueue(maxSize, new Comparator<E>() {
public int compare(E o1, E o2) {
// 生成最小堆使用o2-o1,生成最大堆使用o1-o2, 并修改 e.compareTo(peek) 比较规则
return o1.compareTo(o2);
}
});
}
public void add(E e) {
if (queue.size() < maxSize) { // 未达到最大容量,直接添加
queue.add(e);
} else { // 队列已满
E peek = queue.peek(); //如果o2-o1 大于0 那么队列头元素是最大的,要得到的是最小堆,那么就是留peek和e的较小值
//同样类似的o1-o2,对头元素是最小的,要生成最大堆,保留peek和e的较大者
if (peek.compareTo(e) < 0) { // 将新元素与当前堆顶元素比较,保留较大的元素
queue.poll();
queue.add(e);
}
}
}
//队列中是否包含该元素
public boolean contains(E e){
return queue.contains(e);
}
//队列实际元素个数
public int getSize() {
return queue.size();
}
public List<E> reverse(){
List<E> resultList = new ArrayList<E>(maxSize);
while (!this.queue.isEmpty()) {
resultList.add(queue.poll());
}
Collections.reverse(resultList);
return resultList;
}
public static void main(String[] args) {
final FixSizedPriorityQueue<Integer> pq = new FixSizedPriorityQueue(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.println(rNum);
pq.add(rNum);
}
System.out.println("PriorityQueue 本身的遍历是无序的:-----------------------------------");
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 排序后的遍历:-----------------------------------");
List<Integer> reverse = pq.reverse();
System.out.println(reverse);
}
}