c++实现优先队列

优先队列

优先队列是计算机科学中的一类抽象数据类型。优先队列中的每个元素都有各自的优先级,优先级最高的元素最先得到服务;优先级相同的元素按照其在优先队列中的顺序得到服务。优先队列往往用堆来实现。

典型实现
出于性能考虑,优先队列用堆来实现,具有O(log n)时间复杂度的插入元素性能,O(n)的初始化构造的时间复杂度。如果使用自平衡二叉查找树,插入与删除的时间复杂度为O(log n),构造二叉树的时间复杂度为O(n log n)。从计算复杂度的角度,优先级队列等价于排序算法。

代码示例 (详情见代码注释)

#include <iostream>
using namespace std;

class PriorityQueue
{
private:
	int* pArray;
	int m_length;
public:
	PriorityQueue(int N) {
		// 为后续根节点直接从1开始作准备
		pArray = new int[N + 1];
		m_length = 0;
	}

	int delMax() {
		// 大根堆第一个元素为最大
		int max = pArray[1];
		// 将第一个元素和最后一个元素交换,并使长度减一,即删除最大的元素
		swap(pArray[1], pArray[m_length--]);
		// 防止对象游离
		pArray[m_length + 1] = NULL;
		// 下沉恢复堆的有序性
		sink(1);
		// 返回最大的节点值
		return max;

	}

	void insert(int v) {
		// 将值v插入到pArray[1]位置处,所以这里用的前置++
		pArray[++m_length] = v;
		// 新加入的元素上浮
		swim(m_length);
	}

	// 判断是否为空
	bool isEmpty() {
		return m_length == 0;
	}

	int size() {
		return m_length;
	}

	// 向上浮
	void swim(int k) {
		// 判断最下层的叶子节点值如果大于其父节点则进入循环上浮
		while (k > 1 && pArray[k] > pArray[k / 2]) {
			// 交换父节点和子节点
			swap(pArray[k / 2], pArray[k]);
			// k数值减小继续向上浮
			k /= 2;
		}
	}

	// 向下沉
	void sink(int k) {
		while (2 * k <= m_length)
		{
			// 由于堆的性质父节点为k则其左子树为2*k即j
			int j = 2 * k;
			// 这里先比较左子树和右子树的大小,将最大的那个键记录下来再和父节点比较
			if (j < m_length && (pArray[j] < pArray[j + 1])) j++;
			// 和父节点比较如果父节点比最大的子节点还要大,则直接退出循环
			if (pArray[k] > pArray[j]) break;
			// 如果父节点比子节点小则交换
			swap(pArray[k], pArray[j]);
			// k值变大继续下沉
			k = j;
		}
	}
};

int main() {
	PriorityQueue pq(5);
	pq.insert(2);
	pq.insert(11);
	pq.insert(6);
	pq.insert(1);
	pq.insert(15);

	cout << pq.delMax() << endl;
	cout << pq.delMax() << endl;
	cout << pq.delMax() << endl;
	cout << pq.delMax() << endl;
	cout << pq.delMax() << endl;
	return 0;
}

参考:
https://zh.wikipedia.org/wiki/%E5%84%AA%E5%85%88%E4%BD%87%E5%88%97
算法第四版 p202

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值