小根堆PriorityQueue

认识PriorityQueue

PriorityQueue是从JDK1.5开始提供的新的数据结构接口,它是一种基于优先级堆的极大优先级队列。优先级队列是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优先权的元素。如果不提供Comparator的话,优先队列中元素默认按自然顺序排列,也就是数字默认是小的在队列头,字符串则按字典序排列(参阅 Comparable),也可以根据 Comparator 来指定,这取决于使用哪种构造方法。优先级队列不允许 null 元素。依靠自然排序的优先级队列还不允许插入不可比较的对象(这样做可能导致 ClassCastException)。
比如队列 1 3 5 10 2 自动会被排列 1 2 3 5 10

应用:求一组数据第k大的数

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Random;
 
//固定容量的优先队列,模拟大顶堆,用于解决求topN小或 topk大的问题
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) {
                // 生成最大堆使用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(10); //返回前k=10位
            Random random = new Random();
             int rNum = 0;
            System. out.println("100 个 0~999 之间的随机数:-----------------------------------" );
             for (int i = 1; i <= 100; i++) {
                  rNum = random.nextInt(1000);
                  System. out.print(rNum+"\t" );
                   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() + ", ");
            }
      }
}  

文章来源

猜你喜欢

转载自blog.csdn.net/weixin_44593985/article/details/88632401