优先队列

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);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值