1.最大优先队列
1.定义
可以获取并删除队列中最大的值
2.API设计
3.代码实现
package com.caopeng.ZTestpackage.priority;
public class MaxPriorityQueue<T extends Comparable<T>> {
// 用来存储元素的数组
private T[] items;
// 记录队列中元素的个数
private int N;
public MaxPriorityQueue(int capacity) {
items = (T[])new Comparable[capacity];
N = 0;
}
/**
* 判断索引i处元素是否小于索引j处元素
* @param i
* @param j
* @return
*/
private boolean less(int i,int j){
return items[i].compareTo(items[j]) < 0;
}
private void exch(int i,int j){
T temp = items[i];
items[i] = items[j];
items[j] = temp;
}
/**
* 删除队列中最大的元素,并返回值
* @return
*/
public T delMax(){
T max = items[1];
exch(1,N);
items[N] = null;
N--;
sink(1);
return max;
}
/**
* 往队列中插入一个元素
* @param t
*/
public void insert(T t){
items[++N] = t;
swim(N);
}
/**
* 上浮算法
* @param k
*/
private void swim(int k){
while(k > 1){
if (less(k/2,k)) exch(k,k/2);
k = k/2;
}
}
/**
* 下沉算法
* @param k
*/
private void sink(int k){
while (2*k <= N){
int max = 2*k;
if (2*k+1 <= N){
if (less(2*k,2*k+1)) max = 2*k+1;
}
if (less(max,k)) break;
exch(max,k);
k = max;
}
}
/**
* 获取队列中元素的个数
* @return
*/
public int size(){
return this.N;
}
public boolean isEmpty(){
return this.N == 0;
}
public static void main(String[] args) {
// 创建优先队列
MaxPriorityQueue<String> queue = new MaxPriorityQueue<>(10);
// 往队列中存储元素
queue.insert("A");
queue.insert("B");
queue.insert("C");
queue.insert("D");
queue.insert("E");
queue.insert("F");
queue.insert("G");
// 通过循环从队列中获取最大的元素
while (!queue.isEmpty()){
String max = queue.delMax();
System.out.print(max + " ");
}
}
}
2.最小优先队列
1.定义
可以获取并删除队列中最小的值
2.API设计
3.代码实现
package com.caopeng.ZTestpackage.priority;
public class MinPriorityQueue<T extends Comparable> {
private T[] items;
private int N;
public MinPriorityQueue(int capacity) {
this.items = (T[])new Comparable[capacity];
N = 0;
}
private boolean less(int i,int j){
return items[i].compareTo(items[j]) < 0;
}
private void exch(int i,int j){
T temp = items[i];
items[i] = items[j];
items[j] = temp;
}
public void insert(T t){
items[++N] = t;
swim(N);
}
private void swim(int k){
while(k > 1){
if (less(k,k/2)) exch(k,k/2);
k /= 2;
}
}
private void sink(int k){
while(2*k <= N){
int min = 2*k;
if (2*k+1 <= N) {
if (less(2*k+1,2*k)) min = 2*k+1;
}
if (less(k,min)) break;
exch(k,min);
k = min;
}
}
public T delMin(){
T min = items[1];
exch(1,N);
items[N] = null;
N--;
sink(1);
return min;
}
public int size(){
return this.N;
}
public boolean isEmpty(){
return this.N == 0;
}
public static void main(String[] args) {
// 创建一个最小优先队列
MinPriorityQueue<String> queue = new MinPriorityQueue<String>(10);
// 往队列中添加数据
queue.insert("G");
queue.insert("F");
queue.insert("E");
queue.insert("D");
queue.insert("C");
queue.insert("B");
queue.insert("A");
// 通过循环获取最小优先队列的元素
while(!queue.isEmpty()){
String min = queue.delMin();
System.out.print(min + " ");
}
}
}
3.索引优先队列
1.定义
不仅能快速得到最大或者最小值,还能任意访问队列中的元素
这里以最小索引优先队列为例
2.API设计
3.代码实现
package com.caopeng.ZTestpackage.priority;
public class IndexMinPriorityQueue<T extends Comparable<T>> {
// items数组里面存储了元素的值
private T[] items;
// 保存每个元素在items的索引,pq保持堆有序
private int[] pq;
// 保持pq的逆序,pq的值为qp的索引,pq的索引为qp的值
private int[] qp;
// 数组的长度
private int N;
public IndexMinPriorityQueue(int capacity) {
this.items = (T[]) new Comparable[capacity+1];
this.pq = new int[capacity+1];
this.qp = new int[capacity+1];
this.N = 0;
// 默认情况下,队列中没有存储任何元素,让qp中的元素都为-1
for (int i = 0; i < qp.length; i++) {
qp[i] = -1;
}
}
public boolean isEmpty(){
return this.N == 0;
}
private boolean less(int i, int j){
return items[pq[i]].compareTo(items[pq[j]]) < 0;
}
private void exch(int i,int j){
// 交换pq中的数据
int tmp = pq[i];
pq[i] = pq[j];
pq[j] = tmp;
// 更新qp中的数据(此时pq已经交换完了)
qp[pq[i]] = i;
qp[pq[j]] = j;
}
/**
* 删除队列中最小的元素,并返回该元素关联的索引
* @return
*/
public int delMin(){
// 获取最小元素关联的索引
int minIndex = pq[1];
// 交换pq中索引1处和最大索引处的值
exch(1,N);
// 删除qp中对应的内容
qp[pq[N]] = -1;
// 删除pq最大索引的内容
pq[N] = -1;
// 删除items中对应的值
items[minIndex] = null;
// 元素个数-1
N--;
// 下沉调整
sink(1);
return minIndex;
}
/**
* 往队列中插入一个元素,并且关联索引i
* @param i
* @param t
*/
public void insert(int i,T t){
// 判断i是否已经被关联,如果已经被关联,则不允许插入
if (contains(i)) return;
// 元素加一
this.N++;
// 将数据存储到items对应的i位置处
items[i] = t;
// 把i存储到pq中
pq[N] = i;
// 通过qp来记录pq中的i
qp[i] = N;
// 通过堆上浮来完成堆的调整
swim(N);
}
/**
* 上浮算法
* @param k
*/
private void swim(int k){
while (k > 1){
if (less(k,k/2)) exch(k,k/2);
k = k/2;
}
}
private void sink(int k){
while (2*k <= N){
int min = 2*k;
if (2*k+1 <= N){
if (less(2*k+1,2*k)) min = 2*k+1;
}
if (less(min,k)) exch(min,k);
else break;
}
}
public int size(){
return this.N;
}
/**
* 判断k对应的元素是否存在
* @param k
* @return
*/
public boolean contains(int k){
return qp[k] != -1; // qp的索引是pq的值,pq的值是items数组的索引
}
/**
* 把与索引i关联的元素修改成t
* @param i
* @param t
*/
public void changeItem(int i,T t){
items[i] = t;
int k = qp[i];
sink(k);;
swim(k);
}
/**
* 最小元素关联的索引
* @return
*/
public int minIndex(){
return pq[1];
}
/**
* 删除索引i关联的元素
* @param i
*/
public void delete(int i){
// 找到i在pq中的索引
int k = qp[i];
// 交换pq索引k处的值和索引N处的值
exch(k,N);;
// 删除qp中的内容
qp[pq[N]] = -1;
// 删除pq中的内容
pq[N] = -1;
// 删除items中的内容
items[k] = null;
// 元素个数-1
this.N -- ;
// 堆的调整
swim(k);
sink(k);
}
}