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

它的实现采用了标准库提供的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的一种实现的更多相关文章

  1. 标准库Stack的一种实现

    本文实现了STL中stack的大部分功能,同时添加了一些功能. 注意以下几点: 1.Stack是一种适配器,底层以vector.list.deque等实现 2.Stack不含有迭代器 在本例中,我添加 ...

  2. C++ 异常机制分析(C++标准库定义了12种异常,很多大公司的C++编码规范也是明确禁止使用异常的,如google、Qt)

    阅读目录 C++异常机制概述 throw 关键字 异常对象 catch 关键字 栈展开.RAII 异常机制与构造函数 异常机制与析构函数 noexcept修饰符与noexcept操作符 异常处理的性能 ...

  3. C++ 标准库类型-String,Vector and Bitset

    <C++ Primer 4th>读书摘要 最重要的标准库类型是 string 和 vector,它们分别定义了大小可变的字符串和集合.这些标准库类型是语言组成部分中更基本的那些数据类型(如 ...

  4. 关于标准库中的ptr_fun/binary_function/bind1st/bind2nd

    http://www.cnblogs.com/shootingstars/archive/2008/11/14/860042.html 以前使用bind1st以及bind2nd很少,后来发现这两个函数 ...

  5. Python内置模块与标准库

    Python内置模块就是标准库(模块)吗?或者说Python的自带string模块是内置模块吗? 答案是:string不是内置模块,它是标准库.也就是说Python内置模块和标准库并不是同一种东西. ...

  6. Python标准库:1. 介绍

    标准库包括了几种不同类型的库. 首先是那些核心语言的数据类型库,比方数字和列表相关的库.在核心语言手冊里仅仅是描写叙述数字和列表的编写方式,以及它的排列,而未定义它的语义. 换一句话说,核心语言手冊仅 ...

  7. C++标准库(体系结构与内核分析)(侯捷第二讲)

    一.OOP和GP的区别(video7) OOP:面向对象编程(Object-Oriented programming) GP:泛化编程(Generic programming) 对于OOP来说,我们要 ...

  8. 谈谈两种标准库类型---string和vector

    两种最重要的标准库---string和vector string和vector是两种最重要的标准库类型,string表示可变长的字符序列,vector存放的是某种给定类型对象的可变长序列. 一.标准库 ...

  9. 140种Python标准库、第三方库和外部工具

    导读:Python数据工具箱涵盖从数据源到数据可视化的完整流程中涉及到的常用库.函数和外部工具.其中既有Python内置函数和标准库,又有第三方库和工具. 这些库可用于文件读写.网络抓取和解析.数据连 ...

随机推荐

  1. 洛谷P3144 [USACO16OPEN]关闭农场Closing the Farm

    农夫约翰和他的奶牛准备去旅行,所以约翰想要把他的农场临时关闭. 农场有N个牛棚(牛棚从1到N编号),有M条路连接这些牛棚(1≤N,M≤3000). 约翰打算挨个关闭牛棚,在关牛棚的时候, 他突然想起一 ...

  2. 【一】ODB - C++ 访问数据库的利器--Hello World On Windows(Version-24)

    本文以MySQL数据库为例,其他数据类似. 官方文档和下载 ODB官方首页    官方开发者说明书(开发教程) 安装下载首页(下载与安装教程Windows/Linux) Windows安装步骤(都是英 ...

  3. android的百度地图开发(一)

    1,注册百度开发者账号 2,申请key  ,注意开发版SH和发布版的SH  获取开发版SHA1: 输入命令:keytool -list -v -keystore debug.keystore,回车输入 ...

  4. 关于多态的理解,有助于理解TStream抽象类的多态机制。

    有的时候 不是很明白流的机制,因为有内存流  文件流 图片流 等等 他们之间的相互转化 靠的就是流的多态性.... unit Unit11; interface uses Winapi.Windows ...

  5. Jquery学习之路(二) 实现table样式的设定

    上一篇jquery实现checkbox的全选,得到了一些朋友的建议,其中插件的定义我的确不太清楚,也闹了个笑话,有些朋友建议我去看<锋利的Jquery>,说实话正在看了.由于正在学习中,我 ...

  6. css3帮你轻松实现圆角效果,不一样的前端页面。

    在Web前端页面实现圆角效果,CSS3帮你轻松实现,一个人人皆知的属性 圆角边框的绘制是Web页面和Web应用程序中经常用来美化页面效果的手法之一.今天,小编为大家介绍CSS3提供的可以将矩形变为圆角 ...

  7. 牛客网 牛客小白月赛5 I.区间 (interval)-线段树 or 差分数组?

    牛客小白月赛5 I.区间 (interval) 休闲的时候写的,但是写的心情有点挫,都是完全版线段树,我的一个队友直接就水过去了,为啥我的就超内存呢??? 试了一晚上,找出来了,多初始化了add标记数 ...

  8. 2017 CCPC 湘潭邀请赛

    都tm快一年了我还没补这套题……再不补怕是要留给退役后乐 Problem A 把$n * (n + 1)$的矩阵补成$(n + 1) * (n + 1)$的,然后高斯消元. Problem B 一看题 ...

  9. 理解css的BFC

    BFC是CSS中一个看不见的盒子,(先理解CSS的盒子模型).它的页面渲染方式与普通流的盒子模型不同,它决定了其子元素将如何定位(所用属于BFC的box 都默认左对齐),以及和其他元素的关系和相互作用 ...

  10. Java里如何判断一个String是空字符串或空格组成的字符串

      要判读String是否为空字符串,比较简单,只要判断该String的length是否为0就可以,或者直接用方法isEmpty()来判断. 但很多时候我们也会把由一些不可见的字符组成的String也 ...