# 优先队列（优先级队列、堆）

package algorithm02;
//maxPriorityQueue
public class MaxPQ<any extends Comparable<? super any>> {
//用于存储优先队列元素的数组，数组的位置0不用，从位置1开始存储
private any[] array;
//代表当前优先队列中的元素数量，即优先队列的长度
private int currentSize;
//构造器，需要初始化优先队列的最大存储数量
public MaxPQ(int length){
array = (any[]) new Comparable[length+1];
currentSize = 0;
}
//插入元素的方法，
public void insert(any x) {
if(currentSize == array.length-1) {
enlargeArray(currentSize * 2 + 1);
}
int hole = ++currentSize;
for(array[0]=x;x.compareTo(array[hole/2])>0;hole=hole/2) {
array[hole] = array[hole/2];
}
array[hole] = x;
}
//找出优先队列中的最大值
public any findMax() throws Exception {
if(isEmpty()) {
throw new Exception();
}
return array[1];
}
//找出、返回、并删除优先队列中的最大值
public any deleteMax() throws Exception {
if(currentSize==0) {
throw new Exception();
}
any max = findMax();
array[1] = array[currentSize--];
sink(1);
return max;
}
//判断优先队列是否为空
public boolean isEmpty() {
return currentSize==0;
}
//将优先队列置为空
public void makeEmpty() {
currentSize = 0;
}
//工具方法，扩容数组
private void enlargeArray(int newLength) {
@SuppressWarnings("unchecked")
any[] newArray = (any[]) new Comparable[newLength];
for(int i=1;i<=currentSize;i++) {
newArray[i] = array[i];
}
array = newArray;
}
//工具方法，下沉
private void sink(int hole) {
int child;
any temp = array[hole];
for(;hole*2<=currentSize;hole=child) {
child = hole * 2;
if(child!=currentSize && array[child+1].compareTo(array[child])>0) {
child++;
}
if(array[child].compareTo(array[hole])>0) {
array[hole] = array[child];
}
}
array[hole] = temp;
}
}
package algorithm02;
//minPriorityQueue
public class MinPQ<any extends Comparable<? super any>> {
//当前优先队列中存储的元素数量
private int currentSize;
//实现优先队列的基础数据结构，实际存储元素值，位置0用作哨兵
private any[] array;
//构造器，初始化优先队列的最大存储数量
public MinPQ(int length) {
currentSize = 0;
array = (any[])new Comparable[length+1];
}
//待初始元素的构造器
public MinPQ(any[] items) {
currentSize = items.length;
array = (any[])new Comparable[currentSize+1];

int i = 1;
for(any item : items) {
array[i++] = item;
}

buildHeap();
}
//插入一个元素
public void insert(any x) {
if(currentSize == array.length-1) {
enlargeArray(2*currentSize + 1);
}
int hole = ++currentSize;
for(array[0]=x;x.compareTo(array[hole/2])<0;hole=hole/2) {
array[hole] = array[hole/2];
}
array[hole] = x;
}
//找出优先队列中优先级最大的元素
public any findMin() throws Exception {
if(isEmpty()) {
throw new Exception();
}
return array[1];
}
//找到、返回、并删除优先队列中优先级最大的元素
public any deleteMin() throws Exception {
if(isEmpty()) {
throw new Exception();
}
any min = findMin();
array[1] = array[currentSize--];
sink(1);

return min;
}
//判断优先级队列是否为空
public boolean isEmpty() {
return currentSize==0;
}
//将优先级队列置为空
public void makeEmpty() {
currentSize = 0;
}
//工具方法，下沉
private void sink(int hole){
int child;
any temp = array[hole];

for(;hole*2<=currentSize;hole=child) {
child = hole * 2;
if(child!=currentSize && array[child+1].compareTo(array[child])<0) {
child = child + 1;
}
if(array[child].compareTo(array[hole])<0) {
array[hole] = array[child];
}
}

array[hole] = temp;
}
//工具方法，用于构建有一定数量元素的初始化优先队列
private void buildHeap() {
for(int i=currentSize/2;i>0;i--) {
sink(i);
}
}
//工具方法，对优先队列的数组进行扩容
private void enlargeArray(int newLength) {
@SuppressWarnings("unchecked")
any[] newArray = (any[])new Comparable[newLength];

for(int i=1;i<=currentSize;i++) {
newArray[i] = array[i];
}
array = newArray;
}
}

输出: 5

//优先队列的解决方法
class Solution {
public int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> pq = new PriorityQueue<>();
int count = 0;
for(int num : nums){
count++;
if(count <= k){
pq.offer(num);
}
else if(num > pq.peek()){
pq.poll();
pq.offer(num);
}
}

return pq.peek();
}
}
//快速排序切分思想的解决方法
class Solution {
public int findKthLargest(int[] nums, int k) {
int lo = 0;
int hi = nums.length - 1;
k = k - 1;
while(hi > lo){
int j = partition(nums, lo, hi);
if(j == k)
return nums[k];
if(k < j)
hi = j - 1;
if(k > j)
lo = j + 1;
}

return nums[k];
}

private int partition(int[] nums, int lo, int hi){
int i = lo;
int j = hi + 1;
int v = nums[lo];

while(true){
while(less(v, nums[++i])){
if(i == hi)
break;
}
while(less(nums[--j], v)){
if(j == lo)
break;
}
if(i >= j)
break;
exch(nums, i, j);
}
exch(nums, lo, j);

return j;
}

private boolean less(int a, int b){
return (b-a)>0;
}

private void exch(int[] nums, int i, int j){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}