标准库priority_queue的一种实现
优先级队列相对于普通队列,提供了插队功能,每次最先出队的不是最先入队的元素,而是优先级最高的元素。
它的实现采用了标准库提供的heap算法。该系列算法一共提供了四个函数。使用方式如下:
首先,建立一个容器,放入元素:
vector<int> 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 <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std; template <typename T>
void insertNums(T &t, int beg, int end)
{
while(beg <= end)
{
t.insert(t.end(), beg);
++beg;
}
} template <typename T>
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<int> 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 <vector>
#include <algorithm>
#include <functional> template <typename T,
typename Container = std::vector<T>,
typename Compare = std::less<typename Container::value_type> >
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 <class InputIterator>
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 <typename T, typename Container, typename Compare>
PriorityQueue<T, Container, Compare>::PriorityQueue(const Compare& comp,
const Container& ctnr)
:comp_(comp), cont_(ctnr)
{
std::make_heap(cont_.begin(), cont_.end(), comp_); //建堆
} template <typename T, typename Container, typename Compare>
template <class InputIterator>
PriorityQueue<T, Container, Compare>::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 <iostream>
using namespace std; int main(int argc, char const *argv[])
{
PriorityQueue<float> 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;
}
标准库priority_queue的一种实现的更多相关文章
- 标准库Stack的一种实现
本文实现了STL中stack的大部分功能,同时添加了一些功能. 注意以下几点: 1.Stack是一种适配器,底层以vector.list.deque等实现 2.Stack不含有迭代器 在本例中,我添加 ...
- C++ 异常机制分析(C++标准库定义了12种异常,很多大公司的C++编码规范也是明确禁止使用异常的,如google、Qt)
阅读目录 C++异常机制概述 throw 关键字 异常对象 catch 关键字 栈展开.RAII 异常机制与构造函数 异常机制与析构函数 noexcept修饰符与noexcept操作符 异常处理的性能 ...
- C++ 标准库类型-String,Vector and Bitset
<C++ Primer 4th>读书摘要 最重要的标准库类型是 string 和 vector,它们分别定义了大小可变的字符串和集合.这些标准库类型是语言组成部分中更基本的那些数据类型(如 ...
- 关于标准库中的ptr_fun/binary_function/bind1st/bind2nd
http://www.cnblogs.com/shootingstars/archive/2008/11/14/860042.html 以前使用bind1st以及bind2nd很少,后来发现这两个函数 ...
- Python内置模块与标准库
Python内置模块就是标准库(模块)吗?或者说Python的自带string模块是内置模块吗? 答案是:string不是内置模块,它是标准库.也就是说Python内置模块和标准库并不是同一种东西. ...
- Python标准库:1. 介绍
标准库包括了几种不同类型的库. 首先是那些核心语言的数据类型库,比方数字和列表相关的库.在核心语言手冊里仅仅是描写叙述数字和列表的编写方式,以及它的排列,而未定义它的语义. 换一句话说,核心语言手冊仅 ...
- C++标准库(体系结构与内核分析)(侯捷第二讲)
一.OOP和GP的区别(video7) OOP:面向对象编程(Object-Oriented programming) GP:泛化编程(Generic programming) 对于OOP来说,我们要 ...
- 谈谈两种标准库类型---string和vector
两种最重要的标准库---string和vector string和vector是两种最重要的标准库类型,string表示可变长的字符序列,vector存放的是某种给定类型对象的可变长序列. 一.标准库 ...
- 140种Python标准库、第三方库和外部工具
导读:Python数据工具箱涵盖从数据源到数据可视化的完整流程中涉及到的常用库.函数和外部工具.其中既有Python内置函数和标准库,又有第三方库和工具. 这些库可用于文件读写.网络抓取和解析.数据连 ...
随机推荐
- c/c++: c++函数返回类型什么情况带const
c++ 函数的返回类型,包括const 什么时候起作用呢? 函数返回值不想其立即修改的. 例子如下,这是一个简单的避免产生隐形返回变量的方法,abc 的函数返回是引用,main函数中第10行,++ 操 ...
- luogu 2709 小B的询问 莫队
题目链接 Description 小B有一个序列,包含\(N\)个\(1-K\)之间的整数.他一共有\(M\)个询问,每个询问给定一个区间\([L..R]\),求\(\sum_{i=1}^{K}c_i ...
- java基础练习 15
import java.util.Scanner; public class Fiftheen { /*有n个人围成一圈,顺序排号.从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下 ...
- Hashmap与Hashtable的区别及Hashmap的原理
Hashtable和HashMap有几个主要的不同:线程安全以及速度.仅在你需要完全的线程安全的时候使用Hashtable,而如果你使用Java 5或以上的话,请使用ConcurrentHashMap ...
- jmeter 多机负载压测与服务器性能监测
环境: jmeter: apache-jmeter-3.3 jdk: 负载生成: 被测机: 一. 多机负载压测: 概述: 1.修改jmeter.properties配置文件 remote_hosts= ...
- JUnit--BeforeClass、AfterClass、Before、After示例
JUnit 4 使用 Java 5 中的注解(annotation),以下是JUnit 4 常用的几个 annotation 介绍@Before:初始化方法@After:释放资源@Test:测试方法, ...
- [BZOJ1193][HNOI2006]马步距离 大范围贪心小范围爆搜
1193: [HNOI2006]马步距离 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1988 Solved: 905[Submit][Statu ...
- 计蒜客 17119.Trig Function-切比雪夫多项式+乘法逆元 (2017 ACM-ICPC 亚洲区(西安赛区)网络赛 F)
哈哈哈哈哈哈哈哈哈哈哈哈,终于把这道题补出来了_(:з」∠)_ 来写题解啦. _(:з」∠)_ _(:з」∠)_ _(:з」∠)_ _(:з」∠)_ _(:з」∠)_ 哈哈哈哈哈哈,从9月16日打了这 ...
- HDU 2191 【多重背包】
Input 输入数据首先包含一个正整数C,表示有C组测试用例,每组测试用例的第一行是两个整数n和m(1<=n<=100, 1<=m<=100),分别表示经费的金额和大米的种类, ...
- codevs 2837 考前复习——01背包
时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description Aiden马上要考试了,可他还没怎么复习,于是他 ...