菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
70
0

优先队列

原创
05/13 14:22
阅读数 85932

数据结构与算法(五),优先队列

 

这节总结一下优先队列的常用实现方法。

1、基本概念

普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (largest-in,first-out)的行为特征。(百度百科)

抽象数据类型:

优先队列的接口同前面讲到的队列的接口一样,是其基于泛型的API接口代码如下:

public interface Queue<E> {

    //队列是否为空
    boolean isEmpty();

    //队列的大小
    int size();

    //入队
    void enQueue(E element);

    //出队
    E deQueue();
}

2、基于数组实现的优先队列

实现优先队列最简的方法就是基于前面讲到的基于数组的栈的代码,只需对插入或删除操作作相应的更改即可。

2.1、基于有序数组的实现

在栈的代码的插入方法中添加代码,将所有较大的元素向右移动一格,以保证数组有序(和插入排序相同),这里我们可以使用二分查找的方法来找出元素应插入的位置,然后再移动元素。这样最大元素,总是在数组的最右边,其删除操作和栈的实现中一样。

代码:

/**
 * 基于有序数组的实现的优先队列
 * @author Alent
 * @param <E>
 */
public class PriorityQueue<E extends Comparable<E>> implements Queue<E>{
    private E[] elements;
    private int size=0;
    
    @SuppressWarnings("unchecked")
    public PriorityQueue() {
        elements = (E[])new Comparable[1]; 
    }
    
    @Override public int size() {return size;}

    @Override public boolean isEmpty() {return size == 0;}

    @Override
    public void enQueue(E element) {
        if(size == elements.length) {
            resizingArray(2*size);//若数组已满将长度加倍
        }
        elements[size++] = element;
        insertSort(elements);
    }

    @Override
    public E deQueue() {
        E element = elements[--size];
        elements[size] = null;     //注意:避免对象游离
        if(size > 0 && size == elements.length/4) {
            resizingArray(elements.length/2);//小于数组1/4,将数组减半
        }
        return element;
    }
    
    //插入排序,由于前面n-1个元素是有序的,这里只插入最后一个元素
    public void insertSort(E[] a) {
        int N = size -1; //最后一个元素是size-1,不是a.length-1
        if(N == 0) return;
        int num = binaryFind(a, a[N], 0, N-1);
        E temp = a[N];
        //num后的元素向后移动
        for (int j = N; j > num; j--) {
           a[j] = a[j-1];
        }
        a[num] = temp;
    }

    //找出元素应在数组中插入的位置
    public int binaryFind(E[] a, E temp, int down, int up) {
        if(up<down || up>a.length || down<0) {
            System.out.println("下标错误");
        }
        if(temp.compareTo(a[down]) < 0) return down;
        if(temp.compareTo(a[up]) > 0) return up+1;
        int mid = (up-down)/2 + down;
        if(temp.compareTo(a[mid]) == 0) {
            return mid + 1;
        }else 

这节总结一下优先队列的常用实现方法。

1、基本概念

普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (largest-in,first-out)的行为特征。(百度百科)

抽象数据类型:

优先队列的接口同前面讲到的队列的接口一样,是其基于泛型的API接口代码如下:

public interface Queue<E> {

    //队列是否为空
    boolean isEmpty();

    //队列的大小
    int size();

    //入队
    void enQueue(E element);

    //出队
    E deQueue();
}

2、基于数组实现的优先队列

实现优先队列最简的方法就是基于前面讲到的基于数组的栈的代码,只需对插入或删除操作作相应的更改即可。

2.1、基于有序数组的实现

在栈的代码的插入方法中添加代码,将所有较大的元素向右移动一格,以保证数组有序(和插入排序相同),这里我们可以使用二分查找的方法来找出元素应插入的位置,然后再移动元素。这样最大元素,总是在数组的最右边,其删除操作和栈的实现中一样。

代码:

/**
 * 基于有序数组的实现的优先队列
 * @author Alent
 * @param <E>
 */
public class PriorityQueue<E extends Comparable<E>> implements Queue<E>{
    private E[] elements;
    private int size=0;
    
    @SuppressWarnings("unchecked")
    public PriorityQueue() {
        elements = (E[])new Comparable[1]; 
    }
    
    @Override public int size() {return size;}

    @Override public boolean isEmpty() {return size == 0;}

    @Override
    public void enQueue(E element) {
        if(size == elements.length) {
            resizingArray(2*size);//若数组已满将长度加倍
        }
        elements[size++] = element;
        insertSort(elements);
    }

    @Override
    public E deQueue() {
        E element = elements[--size];
        elements[size] = null;     //注意:避免对象游离
        if(size > 0 && size == elements.length/4) {
            resizingArray(elements.length/2);//小于数组1/4,将数组减半
        }
        return element;
    }
    
    //插入排序,由于前面n-1个元素是有序的,这里只插入最后一个元素
    public void insertSort(E[] a) {
        int N = size -1; //最后一个元素是size-1,不是a.length-1
        if(N == 0) return;
        int num = binaryFind(a, a[N], 0, N-1);
        E temp = a[N];
        //num后的元素向后移动
        for (int j = N; j > num; j--) {
           a[j] = a[j-1];
        }
        a[num] = temp;
    }

    //找出元素应在数组中插入的位置
    public int binaryFind(E[] a, E temp, int down, int up) {
        if(up<down || up>a.length || down<0) {
            System.out.println("下标错误");
        }
        if(temp.compareTo(a[down]) < 0) return down;
        if(temp.compareTo(a[up]) > 0) return up+1;
        int mid = (up-down)/2 + down;
        if(temp.compareTo(a[mid]) == 0) {
            return mid + 1;
        }else 

发表评论

0/200
70 点赞
0 评论
收藏