普通的队列是一种先进先出的数据结构,元素先在队列尾追加、而从队列头删除。

优先队列按照其作用不同,可以分为以下两种:

        最大优先队列:
                可以获取并删除队列中最大的值;

        最小优先队列:

可以获取并删除队列中最小的值。

最大优先队列api设计:
堆这种结构可以方便删除最大的值,所以,我们可以基于堆区实现最大优先队列。

java 优先队列重写compareto怎么写 java优先队列实现_数据结构

package com.yyy;

//继承Comparable接口,给每个数据提供比较规则
public class MaxPriorityQueue<T extends Comparable<T>> {
    //记录堆中元素的个数
    private int N;
    //记录堆中元素的个数
    private T[] items;
    //创建容量为capacity的MaxPriorityQueue对象
    public MaxPriorityQueue(int capacity){
        this.N=0;
        this.items = (T[]) new Comparable[capacity + 1];
    }
    //判断堆中索引i处的元素是否小于索引j处的元素
    private boolean less(int i,int j){
        return items[i].compareTo(items[j])<0;
    }
    //交换堆中i索引和j索引处的值
    private void exch(int i,int j){
        T tmp = items[i];
        items[i]=items[j];
        items[j]=tmp;
    }
    //删除队列中最大的元素,并返回这个最大元素
    public T delMax(){
        if(N==0){
            return null;
        }
        T max=  items[1];
        exch(1,N);
        N--;//把最大的数据放到最后,最小的数据放到第一个结点,N--就删除了最后一个结点
        sink(1);//将换过来的结点进行下沉
        return max;
    }
    //往队列中插入一个元素
    public void insert(T t){
            items[++N]=t;
            swim(N);
    }
    //使用上浮算法,使索引k处的元素能处在一个正确的位置
    private void swim(int k){
        while(k>1){
            if(less(k/2,k)){
                exch(k/2,k);
            }
            k=k/2;
        }
    }
    //使用下沉算法,使索引K处元素处于一个正确的位置
    private void sink(int k){
        while (2*k<=N){
            //1.找出当前结点的较大的子结点
            int max;
            if(2*k+1<=N){
                if (less(2*k,2*k+1)){
                    max=2*k+1;
                }else{
                    max=2*k;
                }
            }else{
                max=2*k;
            }
            if(!less(k,max)){//k>=max,则退出
                break;
            }
            exch(k,max);
            k=max;
        }
    }
    //获取队列中元素的个数
    public int size(){
        return N;
    }
    //判断队列是否为空
    public boolean isEmpty(){
        return N==0;
    }
}

测试代码:

package test;

import com.yyy.MaxPriorityQueue;

public class MaxPriorityQueueTest {
    //创建优先队列
    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");
        //通过循环从队列中获取最大的元素
        while(!queue.isEmpty()){
            String max = queue.delMax();
            System.out.println(max+"  ");
        }

    }
}

最小优先队列api设计:

java 优先队列重写compareto怎么写 java优先队列实现_java_02

 代码实现:
 

package com.yyy;

public class MinPriorityQueue<T extends Comparable<T>> {
    //用来存储元素的数组
    private T[] items;
    //记录堆中元素的个数
    private int N;
    //创建容量为capacity的MinPriorityQueue对象
    public MinPriorityQueue(int capacity){
        this.items = (T[]) new Comparable[capacity + 1];
        this.N=0;
    }
    //判断堆中索引i处的元素是否小于索引j处的元素
    private boolean less(int i,int j){
        return items[i].compareTo(items[j])<0;
    }
    //交换索引i和索引j处的值
    private void exch(int i,int j){
        T tmp = items[i];
        items[i]=items[j];
        items[j]=tmp;
    }
    //删除队列中最小的元素,并返回这个最小元素
    public T delMin(){
        if(N==0){
            return null;
        }
        T min=items[1];
        exch(1,N);//把最小的元素放到最后,最末的一个数据放到第一个结点,N--就删除了最后一个元素
        N--;
        sink(1);
        return min;
    }
    //使用下沉算法,使索引k处的元素能处在一个正确的位置
    private void sink(int k){
        if(k<1) {
            return;
        }
        int min;
        while(2*k<=N){
            if(2*k+1<=N){
                if(less(2*k,2*k+1)){
                    min=2*k;
                }else{
                    min=2*k;
                }
            }else{
                    min=2*k;
            }
            if(less(k,min)){//k>=min,则退出,否则进行后续的步骤
                break;
            }
            exch(k,min);
            k=min;
        }
    }
    //往队列中插入一个元素
    public void insert(T t){
        N++;
        items[N]=t;
        swim(N);
    }
    //使用上浮算法,使索引k处的元素能在堆中处于一个正确的位置
    private void swim(int k){
        if(N<1){
            return ;
        }
        while(k/2>0){
            if(less(k,k/2)){
                exch(k,k/2);
            }
            k=k/2;
        }
    }
    //获取队列中元素的个数
    public int size(){
        return N;
    }
    //判断队列是否为空
    public boolean isEmpty(){
        return N==0;
    }
}

测试代码:
 

package test;

import com.yyy.MinPriorityQueue;

public class MinPriorityQueueTest {
    public static void main(String[] args) {
        MinPriorityQueue <String> queue = new MinPriorityQueue <>(10);
        //往队列中存储元素
        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.println(min+"  ");
        }
    }
}