容器适配器(stack、 queue 、priority_queue)源码浅析与使用示例
一、容器适配器
stack
queue
priority_queue
stack、queue、priority_queue 都不支持任一种迭代器,它们都是容器适配器类型,stack是用vector/deque/list对象创建了一个先进后出容器;queue是用deque或list对象创建了一个先进先出容器;priority_queue是用vector/deque创建了一个排序队列,内部用二叉堆实现。
前面或多或少谈到过list/vector的实现,而没提到过deque的实现,可以用以下一句话概括,具体可以看看《stl源码剖析》:
Storing contents in multiple smaller arrays, allocating additional arrays at the beginning or end as needed.
Indexing is implemented by keeping a dynamic array containing pointers to each of the smaller arrays.
(一)、stack
首先来看示例代码:
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
#include <iostream>
#include <vector> #include <list> #include <stack> using namespace std; int main(void) //for (size_t i=0; i<s.size(); i++) while (!s.empty()) |
再看stack 的源码:
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
// TEMPLATE CLASS stack
template < class _Ty, class _Container = deque<_Ty> > class stack { // LIFO queue implemented with a container public: typedef _Container container_type; typedef typename _Container::value_type value_type; typedef typename _Container::size_type size_type; typedef typename _Container::reference reference; typedef typename _Container::const_reference const_reference; stack() explicit stack(const _Container &_Cont) bool empty() const size_type size() const reference top() const_reference top() const void push(const value_type &_Val) void pop() const _Container &_Get_container() const protected: |
即有一个_Container 成员,默认是deque<_Ty> ,当然也可以传递vector, list 进去,只要支持push_back,pop_back 等接口。内部的函数实现
都借助了容器的函数,跟以前实现过的Stack 很像。
(二)、queue
先来看示例代码:
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
#include <iostream>
#include <vector> #include <list> #include <stack> #include <queue> using namespace std; int main(void) queue<int, list<int> > q; while (!q.empty()) cout << endl; return 0; |
再来看queue 源码:
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
// TEMPLATE CLASS queue
template < class _Ty, class _Container = deque<_Ty> > class queue { // FIFO queue implemented with a container public: typedef _Container container_type; typedef typename _Container::value_type value_type; typedef typename _Container::size_type size_type; typedef typename _Container::reference reference; typedef typename _Container::const_reference const_reference; queue() explicit queue(const _Container &_Cont) bool empty() const size_type size() const reference front() const_reference front() const reference back() const_reference back() const void push(const value_type &_Val) void pop() const _Container &_Get_container() const protected: |
实现跟stack 是很类似的,只是queue不能用vector 实现,因为没有pop_front 接口。
(三)、priority_queue
先来看示例代码:
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#include <iostream>
#include <functional> #include <vector> #include <list> #include <stack> #include <queue> using namespace std; int main(void) while (!q.empty()) cout << endl; return 0; |
再来看priority_queue 的源码:
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
// TEMPLATE CLASS priority_queue
template < class _Ty, class _Container = vector<_Ty>, class _Pr = less<typename _Container::value_type> > class priority_queue { // priority queue implemented with a _Container public: typedef _Container container_type; typedef typename _Container::value_type value_type; typedef typename _Container::size_type size_type; typedef typename _Container::reference reference; typedef typename _Container::const_reference const_reference; priority_queue() explicit priority_queue(const _Pr &_Pred) priority_queue(const _Pr &_Pred, const _Container &_Cont) template<class _Iter> template<class _Iter> template<class _Iter> bool empty() const size_type size() const const_reference top() const reference top() void push(const value_type &_Pred) void pop() protected: |
priority_queue 的实现稍微复杂一点,可以传递3个参数,而且有两个成员,comp 即自定义比较逻辑,默认是less<value_type>,在构造函数中
调用make_heap函数构造二叉堆,comp 主要是用于构造二叉堆时的判别,如果是less
则构造大堆,如果传递greater 则构造小堆.
注意,priority_queue 不能用list 实现,因为list 只支持双向迭代器,而不支持随机迭代器。
下面举个例子说明make_heap 函数的用法:
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#include <iostream>
#include <functional> #include <vector> #include <list> #include <stack> #include <queue> using namespace std; int main(void) copy(a, a + 5, ostream_iterator<int>(cout, " ")); sort(a, a + 5); return 0; |
输出:
5 4 2 1 3
1 2 3 4 5
make_heap() 将容器的元素构造成二叉堆,传递的是less,即构造的是大堆,把大堆层序遍历的结果存入数组,再调用sort()
进行排序,内部调用
的实际算法不一定,可以是堆排序、插入排序、选择排序等等,跟踪进去发现调用的是插入排序;当然也可以直接指定使用堆排序
sort_heap(调用
者必须已经是堆了,也就是前面已经先调用了make_heap,而且大小堆类型得匹配),与make_heap
一样,第三个参数传递的都是函数对象的用
法。sort 和 sort_heap 默认都是从小到大排序,除非重载的版本传递了第三个参数,如下,第三个参数可以是函数指针,也可以是函数对象:
|
1
2 3 4 5 6 7 8 |
// order heap by repeatedly popping, using operator<
template<class _RanIt> inline void sort_heap(_RanIt _First, _RanIt _Last); // order heap by repeatedly popping, using _Pred |
传递greater 构造的是小堆,如下图所示:
参考:
C++ primer 第四版
Effective C++ 3rd
C++编程规范
容器适配器(stack、 queue 、priority_queue)源码浅析与使用示例的更多相关文章
- Java 集合系列 06 Stack详细介绍(源码解析)和使用示例
java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...
- Java 集合系列07之 Stack详细介绍(源码解析)和使用示例
概要 学完Vector了之后,接下来我们开始学习Stack.Stack很简单,它继承于Vector.学习方式还是和之前一样,先对Stack有个整体认识,然后再学习它的源码:最后再通过实例来学会使用它. ...
- Java 集合系列Stack详细介绍(源码解析)和使用示例
Stack简介 Stack是栈.它的特性是:先进后出(FILO, First In Last Out). java工具包中的Stack是继承于Vector(矢量队列)的,由于Vector是通过数组实现 ...
- 【转】 Java 集合系列07之 Stack详细介绍(源码解析)和使用示例
概要 学完Vector了之后,接下来我们开始学习Stack.Stack很简单,它继承于Vector.学习方式还是和之前一样,先对Stack有个整体认识,然后再学习它的源码:最后再通过实例来学会使用它. ...
- STL容器适配器 stack, queue
stack是一种后进先出(last in first out)的数据结构.它只有一个出口,如图所示.stack允许新增元素,删除元素,取得最顶端元素.但除了最顶端外,没有其他任何地方可以存储stack ...
- 容器适配器(一):queue
除了标准的顺序容器外,STL还提供了3种容器适配器,queue,priority_queue和stack 适配器是对顺序容器的包装,它的作用是简化接口. queue接口十分的简单,只有8个方法.再加上 ...
- Java 集合系列 10 Hashtable详细介绍(源码解析)和使用示例
java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...
- Java 集合系列 04 LinkedList详细介绍(源码解析)和使用示例
java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...
- Java 集合系列 09 HashMap详细介绍(源码解析)和使用示例
java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...
随机推荐
- cocos2d-x_lua中tolua++绑定c++分享
cocos2d-x_lua中tolua++绑定c++分享 我用的版本号是cocos2d-x 2.x的版本号 下面操作为了保证不更改引擎的一个类LuaCocos2d.cpp 1.操作前 能够 ...
- [翻译] Canvas 不用写代码的动画
Canvas 不用写代码的动画 https://github.com/CanvasPod/Canvas Canvas is a project to simplify iOS development ...
- 【属性动画示例】Property Animation
MainActivity 属性动画常用操作 // 可操控的属性有:alpha:x/y:scaleX/scaleY:rotation/rotationX/rotationY:transitionX/tr ...
- 今天才知道的JavaScript的真实历史~[转]
JavaScript真的继承自Cmm吗?JavaScript与Java有多少关系?JavaScirpt最初的设计是怎样的?这个文章是从一个叫编程人生的网站上看到的.不知道出处在哪.在许多资料,Java ...
- ftm时钟源
FTMx_SC中的 CLKS时钟选择位 00 :无 01: System clock 10:Fixed frequency clock 11 External clock 此处的01:System c ...
- 红帽RHOP 8 发布一条龙方案
导读 日前,Canonical的Ubuntu在OpenStack的云系统方面处于业界领先地位.其他诸如IBM类顶级科技公司也有意加入OpenStack的混战,新的专用OpenStack公司(例如Mir ...
- Kettle中根据一个输入行派生出多个输出行
依然在北京,早上停电了,整个人感觉对不好了,接下来就说一下在使用ETL工具kettle做数据校验的时候遇到的一些问题,一级解决方案. 1:数据校验效果图下图: 原始表数据(需要校验的表数据) 对上表数 ...
- Hadoop,MapReduce,HDFS面试题
今天发这个的目的是为了给自己扫开迷茫,告诉自己该进阶了,下面内容不一定官方和正确.全然个人理解,欢迎大家留言讨论 1.什么是hadoop 答:是google的核心算法MapReduce的一个开源实现. ...
- ActiveMQ API 详解
4.1 开发JSM的步骤 广义上说,一个JMS 应用是几个JMS 客户端交换消息,开发JMS 客户端应用由以下几步构成: 用JNDI 得到ConnectionFactory 对象: ...
- Linux 内存泄露小结
本文仅限记录自己的一次 内存泄露追踪小记. 可能并不十分适用与大家的情况.而且方法也并不是很smart.仅做记录,能提供个思路更好. 一. 要问调试程序遇到什么问题最头疼, 内存泄露肯定 ...