非严格优先队列-O(1) 时间复杂度

原文转自:http://www.tanjp.com/archives/124(即时修正和更新)分组安全队列 - 非严格优先队列 O(1) 时间复杂度传统的优先队列,都是采用二叉树(堆)的方式来实现,插入和删除都需要维护堆顶元素最大或最小,需要O(logN)的时间复杂度。在某些多线程环境下,把队列当作一个数据交换的纽带,这种开销也是非常大的,于是设计了非严格的优先队列,基满足业务需求...
摘要由CSDN通过智能技术生成

原文转自:http://www.tanjp.com (即时修正和更新)

 

分组安全队列 - 非严格优先队列 O(1) 时间复杂度

传统的优先队列,都是采用二叉树(堆)的方式来实现,插入和删除都需要维护堆顶元素最大或最小,需要O(logN)的时间复杂度。在某些多线程环境下,把队列当作一个数据交换的纽带,这种开销也是非常大的,于是设计了非严格的优先队列,基满足业务需求,同时插入和取出时间复杂度为O(1)。

把队列分为 N 个组,组的编号范围[0, N-1],push时能加入到指定的分组上(也就是能指定优先级),pop时编号越大的组会优先取出(编号越大优先级越高)。

如果只是这样的规则,可能会导致低优先级的元素永远无法取出。

于是,设计了帧的概念,帧数从0开始,每次push时,帧数加一,并记录在一个帧队列里面。当调用pop取出元素后,判断当前组头部元素所属的帧与帧队列头的帧比较,超过指定帧数F时,就把该头部元素加入到最高编号(最高优先级)的组的尾部,也就是说下次会优先从最高组取出(但不一定马上取出,因为是加到最高组的最后)。

概括来说,这是一个不严格的优先队列,当太久前加入的元素没被取出,则提升其优先级,尽可能均衡,而不导致的元素积压过久。这样做避免传统树形结构的优先队列,在每次 push和pop都需要 O(logN)时间复杂度,来调整树的平衡。

分组安全队列的push和pop基本是O(1)的时间复杂度。push的时候只要找到相应的组把元素加入进去并记录在帧队列中就行,时间复杂度O(1)。pop的时候,取出有数据的最高组的头部元素,并比较取出元素的帧数与当前帧队列头部元素的帧数,超过指定值,就触发提高优先级操作,时间复杂度也是O(1)。所以在性能上有很大的优势,当然要根据需求是否能采用这种非严格的优先处理方式。

 

以下是实现代码:

template<typename tpType>
class SafeGroupQueue
{
    	static const uint64 kFrameMaxValue = (std::numeric_limits<uint64>::max() - 1000U); //超过此帧数将会重置
    	static const uint32 kDefaultMaxsize = 4294967290U; //队列容量上限
    	static const uint32 kDefaultUpgradeFrame = 8U; //默认优先处理的帧数
    	static const uint8 kDefaultGroupSize = 5U; //优先队列默认分级大小
    	static const uint8 kDefaultPriorityValue = 2U; //优先队列默认加入分级
    	struct FrameDataType
	{
		FrameDataType(const tpType & po_data, uint64 pn_frame)
			: data(po_data)
			, frame(pn_frame) {}
		tpType data;
		uint64 frame;
	};
	struct FrameGroupType
	{
		FrameGroupType(uint8 pn_priority, uint64 pn_frame)
			: priority(pn_priority)
			, frame(pn_frame) {}
		uint8 priority;
		uint64 frame;
	};
	typedef std::shared_ptr< std::deque<FrameDataType> > QueueType;
public:
	// @pb_block, true为阻塞模式,push和pop操作在边界条件下将会阻塞等待。
	//			false为非阻塞操作,push和pop操作边界条件将会立即返回false。
	// @pn_group_size, 组的大小,取值范围[2, 255]。
	// @pn_upgrade_fr
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值