欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

优先队列

程序员文章站 2022-03-31 08:05:23
...

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

队列:删除最老的元素。

栈:删除最新的元素。

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

优先队列

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

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

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

基于堆的优先队列

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值减一并修复新堆,如此重复直到堆变空。

 优先队列