一、概念
在一些情况下,操作的数据可能带有优先级,一般出队列时,可能需要优先级高的元素出队;在这种的情况下,就可以使用优先级队列:返回最高优先级对象和添加新的对象。
堆的性质:
顺序存储实现堆:
- public int[] elem;
- public int usedSize;
-
- public TestHeap(){
- this.elem = new int[10];
- this.usedSize = 0;
- }
- public void initArray(int[] array){
- elem = Arrays.copyOf(array, array.length);
- usedSize = elem.length;
- }
建大根堆:
- /**
- * 建堆[大根堆]
- */
- public void createHeap(){
- for (int parent = (usedSize-1-1)/2; parent >= 0; parent--) {
- shiftDown(parent,usedSize);
- }
- }
-
- /**
- * 实现向下调整
- * @param parent 每颗子树的根结点的下标
- * @param len
- */
- private void shiftDown(int parent,int len){
- int child = 2*parent+1;
- //最起码有左孩子
- while(child < len){
- //判断左右孩子谁最大,前提 必须有右孩子
- if (child+1 < len&& elem[child] < elem[child+1]){
- child++;//此时保留了最大值下标
- }
- if (elem[child] > elem[parent]){
- swap(elem,child,parent);
- parent = child;
- child = 2*parent+1;
- }else {
- break;
- }
- }
- }
- private void swap(int[] array,int i,int j){
- int tmp = array[i];
- array[i] = array[j];
- array[j] = tmp;
- }
入队:
- public void offer(int x){
- if (isFull()){
- elem = Arrays.copyOf(elem, elem.length*2);
- }
- this.elem[usedSize] = x;
- usedSize++;
- shiftUp(usedSize-1);
- }
-
- private void shiftUp(int child) {
- int parent = (child - 1) / 2;
- while (child > 0) {
- if (elem[child] > elem[parent]) {
- swap(elem, child, parent);
- child = parent;
- parent = (child - 1) / 2;
- } else {
- break;
- }
- }
- }
- private boolean isFull() {
- return usedSize == elem.length;
- }
删除:
- //优先级队列的删除 只能删除堆顶的元素
- public int poll(){
- if (isEmpty()) {
- return -1;
- }
- int old = elem[0];
- swap(elem,0,usedSize-1);
- usedSize--;
- shiftDown(0,usedSize);
- return old;
- }
- private boolean isEmpty(){
- return usedSize == 0;
- }
Java集合框架中提供了PriorityQueue和PriorityBlockingQueue两种类型的优先级队列,PriorityQueue是线程不安全的,PriorityBlockingQueue是线程安全的,本文主要介绍PriorityQueue。

使用PriorityQueue的使用注意:

接口的介绍:


思路一:
- public class Test {
- public static void topK1(int[] array,int k){
- PriorityQueue
priorityQueue = new PriorityQueue<>(new Comparator() { - @Override
- public int compare(Integer o1, Integer o2) {
- return o1 - o2;
- }
- });
- for (int i = 0; i < array.length; i++){
- priorityQueue.offer(array[i]);
- }
- for (int i = 0; i < k; i++) {
- int val = priorityQueue.poll();
- System.out.print(val+" ");
- }
- System.out.println();
- }
- public static void main(String[] args) {
- int[] array = {12,45,32,17,2,18,5,10};
- topK1(array,3);
- }
-
- public static void main1(String[] args) {
- TestHeap testHeap = new TestHeap();
- int[] array = {27,15,19,18,28,34,65,49,25,37};
- testHeap.initArray(array);
- testHeap.createHeap();
- testHeap.offer(100);
- System.out.println();
- }
- }
思路二:
- class Solution {
- public int[] smallestK(int[] array, int k) {
- int[] ret = new int[k];
- if(k == 0){
- return ret;
- }
- PriorityQueue
maxPq = new PriorityQueue<>(k,new Comparator() { - @Override
- public int compare(Integer o1, Integer o2) {
- return o2 - o1;
- }
- });
- for (int i = 0; i < array.length; i++) {
- if (maxPq.size() < k){
- maxPq.offer(array[i]);
- }else {
- int top = maxPq.peek();
- if (array[i] < top){
- maxPq.poll();
- maxPq.offer(array[i]);
- }
- }
- }
- for (int i = 0; i < k; i++) {
- int val = maxPq.poll();
- ret[i] = val;
- }
- return ret;
- }
- }
大根堆实现从小到大排序:
- /**
- * 实现向下调整
- * @param parent 每颗子树的根结点的下标
- * @param len
- */
- private void shiftDown(int parent,int len){
- int child = 2*parent+1;
- //最起码有左孩子
- while(child < len){
- //判断左右孩子谁最大,前提 必须有右孩子
- if (child+1 < len && elem[child] < elem[child+1]){
- child++;//此时保留了最大值下标
- }
- if (elem[child] > elem[parent]){
- swap(elem,child,parent);
- parent = child;
- child = 2*parent+1;
- }else {
- break;
- }
- }
- }
- private void swap(int[] array,int i,int j){
- int tmp = array[i];
- array[i] = array[j];
- array[j] = tmp;
- }
- public void heapSort(){
- int end = usedSize-1;
- while (end > 0){
- swap(elem,0,end);
- shiftDown(0,end);
- end--;
- }
- }