优先队列

Posted ppwq

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了优先队列相关的知识,希望对你有一定的参考价值。

支持两种操作:删除最大元素和插入元素的数据类型叫做优先队列。

队列:删除最老的元素。

栈:删除最新的元素。

基于二叉堆数据结构的一种优先队列的经典实现方法,用数组保存元素并按照一定条件排序。

  数据结构二叉堆能够很好地实现优先队列的基本操作。在二叉堆的数组中,每个元素都要保证大于等于另两个特定位置的元素。相应地,这些位置的元素又至少要大于等于数组中的另两个元素。

  当一个二叉树的每个结点都大于等于它的两个子结点时,它被称为堆有序。根节点是堆有序的二叉树中的最大结点。

  二叉堆是一组能够用堆有序的完全二叉树排序的元素,并在数组中按照层级储存(不适用数组的第一个位置)。

基于堆的优先队列

public class MaxPQ<Key extends Comparable<Key>>
{
	private Key[] pq;             //基于堆的完全二叉树
	private int N = 0;            //存储于pq[1..N]中,pq[0]没有使用
	public MaxPQ(int maxN)
	{	pq = (Key[]) new Comparable[maxN+1];	}
	public boolean isEmpty()
	{	return N == 0;	}
	public int size()
	{	return N;	}
	public void insert(Key v)
	{
		pq[++N] = v;
		swim(N);
	}
	public Key delMax()
	{
		Key max = pq[1];           //从根节点得到最大元素
		exch(1, N--);              //将其和最后一个结点交换
		pq[N+1] = null;            //防止越界
		sink(1);                   //恢复堆的有序性
		return max;
	}
	private boolean less(int i, int j)
	{	return pq[i].compareTo(pq[j]) < 0;	}
	private void exch(int i, int j)
	{	
		Key t = pq[i];
		pq[i] = pq[j];
		pq[j] = t;
	}
	private void swim(int k)
	{	//由下至上的堆有序化(上浮)的实现
		while (k >1 && less(k/2, k))
		{
			exch(k/2, k);
			k = k/2;
		}
	}
	private void sink(int k)
	{	//由上至下的堆有序化(下沉)的实现
		while (2*k <= N)
		{
			int j = 2*k;
			if (j < N && less(j, j+1)) j++;
			if (!less(k, j)) break;
			exch(k, j);
			k = j;
		}
	}
}

  优先队列由一个基于堆的完全二叉树表示,存储于数组pq[1..N]中,pq[0]不使用。若含有N个元素,则插入元素操作只需不超过(lgN+1)次比较,删除最大元素操作需要不超过2lgN次比较。

堆排序

堆排序分为两个阶段。在堆的构造阶段,将原始数据重新组织进一个堆中;然后在下沉排序阶段,我们从堆中按递减顺序取出所有元素并得到排序结果。

public static void sort(Comparable[] a)
{
	int N = a.length;
	for (int k = N/2; k >= 1; k--)
		sink(a, k, N);
	while (N > 1)
	{
		exch(a, 1, N--);
		sink(a, 1, N);
	}
}

  

用sink()方法首先将数组里的元素排序,for循环构造了堆,然后while循环将最大的元素a[1]和a[N]交换,N值减一并修复新堆,如此重复直到堆变空。

 

 

以上是关于优先队列的主要内容,如果未能解决你的问题,请参考以下文章

线性表--08---优先队列

优先队列

优先队列实现dijkstra算法C++代码

基础扩展 | 16. 队列应用示例:广度优先搜索

优先队列代码实现

优先队列与堆