博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
标准库priority_queue的一种实现
阅读量:7039 次
发布时间:2019-06-28

本文共 4559 字,大约阅读时间需要 15 分钟。

hot3.png

优先级队列相对于普通队列,提供了插队功能,每次最先出队的不是最先入队的元素,而是优先级最高的元素。

它的实现采用了标准库提供的heap算法。该系列算法一共提供了四个函数。使用方式如下:

首先,建立一个容器,放入元素:

vector
coll;insertNums(coll, 3, 7);insertNums(coll, 5, 9);insertNums(coll, 1, 4);printElems(coll, "all elements: ");

打印结果为:

all elements: 3 4 5 6 7 5 6 7 8 9 1 2 3 4

然后我们调用make_heap,这个算法把[beg, end)内的元素建立成堆

make_heap(coll.begin(), coll.end());printElems(coll, "after make_heap: ");

打印结果:

after make_heap: 9 8 6 7 7 5 5 3 6 4 1 2 3 4

然后我们调用pop_heap,这个算法必须保证[beg, end)已经是一个heap,然后它将堆顶的元素(其实是begin指向的元素)放到最后,再把[begin. end-1)内的元素重新调整为heap

pop_heap(coll.begin(), coll.end());coll.pop_back();printElems(coll, "after pop_heap: ");

打印结果为:

after pop_heap: 8 7 6 7 4 5 5 3 6 4 1 2 3

接下来我们调用push_heap,该算法必须保证[beg, end-1)已经是一个heap,然后将整个[beg, end)调整为heap

coll.push_back(17);push_heap(coll.begin(), coll.end());printElems(coll, "after push_heap: ");

打印结果为:

after push_heap: 17 7 8 7 4 5 6 3 6 4 1 2 3 5

最后我们使用sort_heap将[beg, end)由heap转化为有序序列,所以,前提是[beg, end)已经是一个heap

sort_heap(coll.begin(), coll.end());printElems(coll, "after sort_heap: ");

打印结果为:

after sort_heap: 1 2 3 3 4 4 5 5 6 6 7 7 8 17

完整的测试代码如下:

#include 
#include
#include
#include
using namespace std;template
void insertNums(T &t, int beg, int end){ while(beg <= end) { t.insert(t.end(), beg); ++beg; } }template
void printElems(const T &t, const string &s = ""){ cout << s << endl; for(typename T::const_iterator it = t.begin(); it != t.end(); ++it) { cout << *it << " "; } cout << endl;}int main(int argc, char const *argv[]){ vector
coll; insertNums(coll, 3, 7); insertNums(coll, 5, 9); insertNums(coll, 1, 4); printElems(coll, "all elements: "); //在这个范围内构造heap make_heap(coll.begin(), coll.end()); printElems(coll, "after make_heap: "); //将堆首放到最后一个位置,其余位置调整成堆 pop_heap(coll.begin(), coll.end()); coll.pop_back(); printElems(coll, "after pop_heap: "); coll.push_back(17); push_heap(coll.begin(), coll.end()); printElems(coll, "after push_heap: "); sort_heap(coll.begin(), coll.end()); printElems(coll, "after sort_heap: "); return 0;}

 

根据以上的算法,我们来实现标准库的优先级队列priority_queue,代码如下:

#ifndef PRIORITY_QUEUE_HPP#define PRIORITY_QUEUE_HPP#include 
#include
#include
template
, typename Compare = std::less
>class PriorityQueue{public: typedef typename Container::value_type value_type; //不用T typedef typename Container::size_type size_type; typedef Container container_type; typedef value_type &reference; typedef const value_type &const_reference; PriorityQueue(const Compare& comp = Compare(), const Container& ctnr = Container()); template
PriorityQueue (InputIterator first, InputIterator last, const Compare& comp = Compare(), const Container& ctnr = Container()); void push(const value_type &val) { cont_.push_back(val); //调整最后一个元素入堆 std::push_heap(cont_.begin(), cont_.end(), comp_); } void pop() { //第一个元素移出堆,放在最后 std::pop_heap(cont_.begin(), cont_.end(), comp_); cont_.pop_back(); } bool empty() const { return cont_.empty(); } size_type size() const { return cont_.size(); } const_reference top() const { return cont_.front(); }private: Compare comp_; //比较规则 Container cont_; //内部容器};template
PriorityQueue
::PriorityQueue(const Compare& comp, const Container& ctnr) :comp_(comp), cont_(ctnr){ std::make_heap(cont_.begin(), cont_.end(), comp_); //建堆}template
template
PriorityQueue
::PriorityQueue (InputIterator first, InputIterator last, const Compare& comp, const Container& ctnr) :comp_(comp), cont_(ctnr){ cont_.insert(cont_.end(), first, last); std::make_heap(cont_.begin(), cont_.end(), comp_);}#endif //PRIORITY_QUEUE_HPP

我们注意到:

1.优先级队列内部保存了排序规则,这与map和set是一致的。

2.前面我们提到heap算法除了make_heap之外,都必须保证之前是一个建好的heap,这里我们在构造函数中调用make_heap,保证了后面的各种heap算法都是合法的。

3.还有一点,如果T与容器的类型不一致,例如PriorityQueue<float, vector<int> >,那么我们的value_type优先采用int,毕竟我们操作的对象是容器。

测试代码如下:

#include "PriorityQueue.hpp"#include 
using namespace std;int main(int argc, char const *argv[]){ PriorityQueue
q; q.push(66.6); q.push(22.3); q.push(44.4); cout << q.top() << endl; q.pop(); cout << q.top() << endl; q.pop(); q.push(11.1); q.push(55.5); q.push(33.3); q.pop(); while(!q.empty()) { cout << q.top() << " "; q.pop(); } cout << endl; return 0;}

转载于:https://my.oschina.net/inevermore/blog/388708

你可能感兴趣的文章
IHttpHandler的那些事
查看>>
springmvc后台取值中文乱码问题
查看>>
自定义控件 二 安装集成自定义的控件
查看>>
IOS开发之代码之九宫格
查看>>
H5滚动轮播插件
查看>>
陶哲轩实分析 命题7.4.3 (级数的重排) 证明
查看>>
基于形态编程设计类
查看>>
数论+DP HDOJ 4345 Permutation
查看>>
windows上搭建eclipse+golang开发环境
查看>>
pdf
查看>>
基础算法--树的概述
查看>>
【BZOJ3622】已经没有什么好害怕的了
查看>>
oracle之 RAC本地数据文件迁移至ASM
查看>>
个人博客开发完成贴
查看>>
EMS SQL Manager中文显示乱码的解决方法
查看>>
使用mysql的长连接
查看>>
LinkedList源码阅读笔记(1.8)
查看>>
Oracle12C查询自建用户(非系统自带)
查看>>
查看堵塞的SQL
查看>>
ASP.NET Core之跨平台的实时性能监控(2.健康检查)
查看>>