基于堆的优先队列(Java实现)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33054265/article/details/82763373

优先队列的最重要的操作:删除最大元素(或最小)和插入元素。数据结构二叉堆能够很好的实现队列的基本操作。
二叉堆的结点按照层级顺序放入数组,用长度为N+1的私有数组pq来表示一个大小为N的堆(堆元素放在pq[1]至pq[N]之间,为方便计数,未使用pq[0]),跟节点在位置1,它的子结点在位置2和3,以此类推。位置k的节点的父节点位置为k/2,它的两个子节点位置分别为2k和2k+1。
当一颗二叉树的每个节点都大于等于它的两个子节点时,称为大根堆。
当一颗二叉树的每个节点都小于等于它的两个子节点时,称为小根堆。

堆(大根堆)的有序化:

  • 由下至上的堆有序化(上浮):如果堆的有序状态因为某个节点变得比它的父节点更大而被打破,就需要交换它和它的父节点来修复堆,以此类推,直到遇到一个更大的父节点。
private void swim(int k){
	while(k > 1 && pq[k] > pq[k / 2]){
		int temp = pq[k];
		pq[k] = pq[k / 2];
		pq[k / 2] = temp;
		k /= 2;
	}
}
  • 由上至下的堆有序化(下沉):如果堆的有序状态因为某个节点变得比它的两个子节点或者其中之一更小而被打破,需要将它和它的两个子节点中的较大者交换来恢复堆,以此类推,直到它的子节点比它更小或者到达堆的底部。
private void sink(int k){
	while(2 * k <= N){
		int j = 2 * k;
		if(j < N && pq[j] < pq[j + 1]){
			j++;
		}
		if(pq[k] >= pq[j]){
			break;
		}
		int temp = pq[k];
		pq[k] = pq[j];
		pq[j] = temp;
		k = j;
	}
}

基于堆的优先队列的Java代码实现:

public class MaxPQ<Key>{
	private Key[] pq;
	private int N = 0;
	public MaxPQ(int maxN){
		pq = new Key[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];//从跟节点得到最大元素
		exchange(1, N--);//将根节点的元素和最后一个节点交换
		pq[N] = null;
		sink(1);//下沉
		return max;
	}
	public void exchange(int i, int j){
		Key temp = pq[i];
		pq[i] = pq[j];
		pq[j] = temp;
	}
}

对于一个含有N个元素的基于堆的优先队列,删除最大元素和插入操作时间复杂度为O(logN)。

猜你喜欢

转载自blog.csdn.net/qq_33054265/article/details/82763373
今日推荐