算法基础三:分治算法---基于二叉堆的优先队列

算法基础三:分治算法---基于二叉堆的优先队列

一、算法描述与分析

​ 堆还有一个作为有效优先队列的应用。优先队列,指的是队列中的元素都被指派了一个优先级,元素按优先级最大(或最小)出队。由于,存储堆的数组的第一个元素就是最大的(或者最小的),所以用堆作为优先队列的元素载体是合适的。

​ 队列有两个基本操作:

  • 入队操作ENQUEUE(Q,e),其中参数Q是优先队列,e是要加入队列的元素。
  • 出队操作DEQUEUE(Q),它将返回Q中优先级最大(最小)的元素。

下面讨论利用最大堆的最大优先队列Q,假定Q是一个最大堆。

1、入队算法描述与分析

​ 对于入队的操作,我们把要加入的元素放在堆的末尾,然后维护堆的性质——从新的末尾开始,若检测到当前元素的优先级大于其父亲节点元素的优先级,两者互换。ENQUEUE

伪代码描述

ENQUEUE(Q,e)
	if heap-size[Q] = length[Q]	//堆的空间已经满了(数组没有多余的空间了)
		then error "堆上溢"
	i <- heap-size[Q] <- heap-size[Q] + 1	//如果堆空间没有满,更新heap-size(已经入堆的元素)
	A[heap-size[Q]] <- e			//把元素放在队的最后面
	while i > 1 and A[PARENT(i)] < A[i]	//从新的末尾开始,若检测到当前元素的优先级大于其父亲节点元素的优先级,两者互换
		do exchange A[i] <-> A[PARENT(i)]
			i <- PARENT(i)

2、出队算法描述与分析

​ 对于出队操作,只要将堆Q中的最大元素(Q[1])“舍弃”:Q[1]的值暂存于max,将Q[heap-size[Q]]赋予Q[1],并使得heap-size减小1.然后维护剩余元素的堆性质,并返回max。

伪代码描述

DEQUEUE(Q)
	if heap-size[Q] < 1
		then error "堆下溢"
	max <- Q[q]
	Q[1] <- Q[heap-size[Q]]
	heap-size[Q] <- heap-size[Q] - 1
	MAX-HEAPIFY (Q,1)
	return max

二、自编程序实现版本

1、算法代码

​ 利用上一节开发的程序,来实现本次的优先队列类PrioQueue;

import java.util.Collections;
import java.util.Comparator;
import java.util.Vector;

public class PrioQueue {

    private Vector<Comparable> heap;
    private int heapSize;
    Comparator comparator;
    public PrioQueue(){
        heapSize = 0;
        heap = new Vector<Comparable>();
        comparator = new Greater();
    }

    public PrioQueue(Comparator comp){
        heapSize = 0;
        heap = new Vector<Comparable>();
        comparator = comp;
    }

    public void enQueue (Comparable e){
        int i = heapSize++;//进入队列加一
        heap.add(e);
        while ((i>0) && (comparator.compare(heap.get(i),heap.get(LinearList.parent(i))) > 0)){
            Collections.swap(heap,LinearList.parent(i),i);
            i = LinearList.parent(i);
        }
    }

    public Comparable deQueue(){
        if (heapSize<1)
            return null;
        Comparable top = heap.get(0);//top <- heap[0]
        heapSize--;
        heap.set(0,heap.get(heapSize)); //heap[0] <- heap[heapSize]
        heap.remove(heapSize); //将heap[heapSize]从heap中删除
        LinearList.heapify(heap,0,heapSize,comparator);
        return top;
    }

    public boolean empty(){
        return heapSize <= 0;
    }
}

2、测试代码

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Vector;

public class TestPrioQueue {
    public static void main(String[] args) {
        Integer a[] = {5,1,9,4,6,2,0,3,8,7},i;
        String b[] = {"ChongQing","ShangHai","AoMen","TianJin","BeiJing","XiangGang"};
        Double c[] = {8.5,6.3,1.7,9.2,0.5,2.3,4.1,7.4,5.9,3.7};

        PrioQueue q = new PrioQueue();
        PrioQueue q1 = new PrioQueue(new Less());
        PrioQueue q2 = new PrioQueue(new Greater());

        for (i=0;i<10;i++){
            q.enQueue(a[i]);
            q2.enQueue(c[i]);
        }

        for (i=0;i<6;i++)
            q1.enQueue(b[i]);

        while (!q.empty())
            System.out.print(q.deQueue()+" ");
        System.out.println();

        while (!q1.empty())
            System.out.print(q1.deQueue()+" ");
        System.out.println();

        while (!q2.empty())
            System.out.print(q2.deQueue()+" ");
        System.out.println();

    }
}

三、Collection Framework的PriorityQueue类

​ Java提供了一个优先队列类PriorityQueue,该类定义在包Java.util中,它有两个构造方法:默认的构造方法PriorityQueue(),创建一个空的最小优先队列PriorityQueue (int n, Comparator comparator)使用比较规则comparator创建一个可以容纳n个元素的优先队列

测试代码

import java.util.PriorityQueue;

public class TestPrioQueue_2 {
    public static void main(String[] args) {
        Integer a[] = {5,1,9,4,6,2,0,3,8,7},i;
        PriorityQueue q = new PriorityQueue(10, new Less());
        PriorityQueue q1 = new PriorityQueue();
        for (i=0;i<10;i++){
            q.add(a[i]);
            q1.add(a[i]);
        }

        while (!q.isEmpty())
            System.out.print(q.poll() + " ");
        System.out.println();

        while (!q1.isEmpty())
            System.out.print(q1.poll()+" ");
        System.out.println();

    }
}
posted @ 2021-09-24 14:04  DarkerG  阅读(57)  评论(0编辑  收藏  举报