一、容器适配器
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

首先来看示例代码:

 C++ Code 
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)
{
    stack<int, list<int> > s;
    for (int i = 0; i < 5; i++)
    {
        s.push(i);
    }

//for (size_t i=0; i<s.size(); i++)
    //{
    //  cout<<s.top()<<' ';   Error:size()一直在变化
    //  s.pop();
    //}

while (!s.empty())
    {
        cout << s.top() << ' ';
        s.pop();
    }
    cout << endl;
    return 0;
}

再看stack 的源码:

 C++ Code 
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()
        : c()
    {
        // construct with empty container
    }

explicit stack(const _Container &_Cont)
        : c(_Cont)
    {
        // construct by copying specified container
    }

bool empty() const
    {
        // test if stack is empty
        return (c.empty());
    }

size_type size() const
    {
        // test length of stack
        return (c.size());
    }

reference top()
    {
        // return last element of mutable stack
        return (c.back());
    }

const_reference top() const
    {
        // return last element of nonmutable stack
        return (c.back());
    }

void push(const value_type &_Val)
    {
        // insert element at end
        c.push_back(_Val);
    }

void pop()
    {
        // erase last element
        c.pop_back();
    }

const _Container &_Get_container() const
    {
        // get reference to container
        return (c);
    }

protected:
    _Container c;   // the underlying container
};

即有一个_Container 成员,默认是deque<_Ty> ,当然也可以传递vector, list 进去,只要支持push_back,pop_back 等接口。内部的函数实现

都借助了容器的函数,跟以前实现过的Stack 很像。

(二)、queue

先来看示例代码:

 C++ Code 
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)
{
    //int a[] = {1, 2, 3, 4, 5};
    //vector<int> v(a, a+5);

queue<int, list<int> > q;
    for (int i = 0; i < 5; i++)
    {
        q.push(i);
    }

while (!q.empty())
    {
        cout << q.front() << ' ';
        q.pop();
    }

cout << endl;

return 0;
}

再来看queue 源码:

 C++ Code 
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()
        : c()
    {
        // construct with empty container
    }

explicit queue(const _Container &_Cont)
        : c(_Cont)
    {
        // construct by copying specified container
    }

bool empty() const
    {
        // test if queue is empty
        return (c.empty());
    }

size_type size() const
    {
        // return length of queue
        return (c.size());
    }

reference front()
    {
        // return first element of mutable queue
        return (c.front());
    }

const_reference front() const
    {
        // return first element of nonmutable queue
        return (c.front());
    }

reference back()
    {
        // return last element of mutable queue
        return (c.back());
    }

const_reference back() const
    {
        // return last element of nonmutable queue
        return (c.back());
    }

void push(const value_type &_Val)
    {
        // insert element at beginning
        c.push_back(_Val);
    }

void pop()
    {
        // erase element at end
        c.pop_front();
    }

const _Container &_Get_container() const
    {
        // get reference to container
        return (c);
    }

protected:
    _Container c;   // the underlying container
};

实现跟stack 是很类似的,只是queue不能用vector 实现,因为没有pop_front 接口。

(三)、priority_queue

先来看示例代码:

 C++ Code 
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)
{
    int a[] = {5, 1, 2, 4, 3};
    priority_queue<int, vector<int>, greater<int> > q(a, a + 5);

while (!q.empty())
    {
        cout << q.top() << ' ';
        q.pop();
    }

cout << endl;

return 0;
}

再来看priority_queue 的源码:

 C++ Code 
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()
        : c(), comp()
    {
        // construct with empty container, default comparator
    }

explicit priority_queue(const _Pr &_Pred)
        : c(), comp(_Pred)
    {
        // construct with empty container, specified comparator
    }

priority_queue(const _Pr &_Pred, const _Container &_Cont)
        : c(_Cont), comp(_Pred)
    {
        // construct by copying specified container, comparator
        make_heap(c.begin(), c.end(), comp);
    }

template<class _Iter>
    priority_queue(_Iter _First, _Iter _Last)
        : c(_First, _Last), comp()
    {
        // construct by copying [_First, _Last), default comparator
        make_heap(c.begin(), c.end(), comp);
    }

template<class _Iter>
    priority_queue(_Iter _First, _Iter _Last, const _Pr &_Pred)
        : c(_First, _Last), comp(_Pred)
    {
        // construct by copying [_First, _Last), specified comparator
        make_heap(c.begin(), c.end(), comp);
    }

template<class _Iter>
    priority_queue(_Iter _First, _Iter _Last, const _Pr &_Pred,
                   const _Container &_Cont)
        : c(_Cont), comp(_Pred)
    {
        // construct by copying [_First, _Last), container, and comparator
        c.insert(c.end(), _First, _Last);
        make_heap(c.begin(), c.end(), comp);
    }

bool empty() const
    {
        // test if queue is empty
        return (c.empty());
    }

size_type size() const
    {
        // return length of queue
        return (c.size());
    }

const_reference top() const
    {
        // return highest-priority element
        return (c.front());
    }

reference top()
    {
        // return mutable highest-priority element (retained)
        return (c.front());
    }

void push(const value_type &_Pred)
    {
        // insert value in priority order
        c.push_back(_Pred);
        push_heap(c.begin(), c.end(), comp);
    }

void pop()
    {
        // erase highest-priority element
        pop_heap(c.begin(), c.end(), comp);
        c.pop_back();
    }

protected:
    _Container c;   // the underlying container
    _Pr comp;   // the comparator functor
};

priority_queue 的实现稍微复杂一点,可以传递3个参数,而且有两个成员,comp 即自定义比较逻辑,默认是less<value_type>,在构造函数中

调用make_heap函数构造二叉堆,comp 主要是用于构造二叉堆时的判别,如果是less
则构造大堆,如果传递greater 则构造小堆.

注意,priority_queue 不能用list 实现,因为list 只支持双向迭代器,而不支持随机迭代器。

下面举个例子说明make_heap 函数的用法:

 C++ Code 
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)
{
    int a[] = {5, 1, 2, 4, 3};
    make_heap(a, a + 5, less<int>());

copy(a, a + 5, ostream_iterator<int>(cout, " "));
    cout << endl;

sort(a, a + 5);
    //  sort_heap(a, a+5, less<int>());
    copy(a, a + 5, ostream_iterator<int>(cout, " "));
    cout << endl;

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 默认都是从小到大排序,除非重载的版本传递了第三个参数,如下,第三个参数可以是函数指针,也可以是函数对象:

 C++ Code 
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
template < class _RanIt,
         class _Pr > inline
void sort_heap(_RanIt _First, _RanIt _Last, _Pr _Pred);

传递greater 构造的是小堆,如下图所示:

参考:

C++ primer 第四版
Effective C++ 3rd
C++编程规范

容器适配器(stack、 queue 、priority_queue)源码浅析与使用示例的更多相关文章

  1. Java 集合系列 06 Stack详细介绍(源码解析)和使用示例

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  2. Java 集合系列07之 Stack详细介绍(源码解析)和使用示例

    概要 学完Vector了之后,接下来我们开始学习Stack.Stack很简单,它继承于Vector.学习方式还是和之前一样,先对Stack有个整体认识,然后再学习它的源码:最后再通过实例来学会使用它. ...

  3. Java 集合系列Stack详细介绍(源码解析)和使用示例

    Stack简介 Stack是栈.它的特性是:先进后出(FILO, First In Last Out). java工具包中的Stack是继承于Vector(矢量队列)的,由于Vector是通过数组实现 ...

  4. 【转】 Java 集合系列07之 Stack详细介绍(源码解析)和使用示例

    概要 学完Vector了之后,接下来我们开始学习Stack.Stack很简单,它继承于Vector.学习方式还是和之前一样,先对Stack有个整体认识,然后再学习它的源码:最后再通过实例来学会使用它. ...

  5. STL容器适配器 stack, queue

    stack是一种后进先出(last in first out)的数据结构.它只有一个出口,如图所示.stack允许新增元素,删除元素,取得最顶端元素.但除了最顶端外,没有其他任何地方可以存储stack ...

  6. 容器适配器(一):queue

    除了标准的顺序容器外,STL还提供了3种容器适配器,queue,priority_queue和stack 适配器是对顺序容器的包装,它的作用是简化接口. queue接口十分的简单,只有8个方法.再加上 ...

  7. Java 集合系列 10 Hashtable详细介绍(源码解析)和使用示例

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  8. Java 集合系列 04 LinkedList详细介绍(源码解析)和使用示例

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  9. Java 集合系列 09 HashMap详细介绍(源码解析)和使用示例

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

随机推荐

  1. HTML5 book响应式翻页效果

    翻页,HTML5源码下载,HTML5响应式翻页效果,鼠标移到右上角会看到翻页效果,需要鼠标拖动后翻页,支持ie9+,html5浏览器. 单页和双页. 自动播放和暂停. 点击左右翻页. 鼠标点击左右页面 ...

  2. 取maven copy部分

    mvn deploy:deploy-file -DgroupId=com.mycompany -DartifactId=my-project -Dversion=1.0.0 -Dpackaging=j ...

  3. 使用Vue.js和Axios从第三方API获取数据 — SitePoint

    更多的往往不是,建立你的JavaScript应用程序时,你会想把数据从远程源或消耗一个[ API ](https:/ /恩.维基百科.org /维基/ application_programming_ ...

  4. Ubuntu删除文件夹的命令

    1. 删除文件夹的内容包括文件夹: rm -rf 文件夹的名字       (-r 是 循环的意思, f是不询问的意思) 2 .删除文件夹的内容不包括文件夹: rm -rf  文件夹的名字/*     ...

  5. UIControl的子类UISwitch, UISegmentedCntrol, UIPageControl详解

    - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typica ...

  6. C 语言高效编程的几招——A few action of efficient C language programming

    编写高效简洁的C 语言代码,是许多软件工程师追求的目标.本文就工作中的一些体会和经验做相关的阐述,不对的地方请各位指教. 第1 招:以空间换时间 计算机程序中最大的矛盾是空间和时间的矛盾,那么,从这个 ...

  7. JAVA , TOMCAT , AXIS2 环境变量配置

    想要成功配置Java的环境变量,那肯定就要安装JDK,才能开始配置的. 安装JDK 向导进行相关参数设置.如图: 正在安装程序的相关功能,如图: 选择安装的路径,可以自定义,也可以默认路径.如图: 成 ...

  8. 设置tomcat配置文件,在Myeclipse中修改jsp文件之后不用重启tomcat

    在Myeclipse中创建的Web程序在修改类或者jsp页面后需要重动ttomcat的,要重新加载一次的,即重新启动tomcat一次.重启时比较慢,及浪费资源及时间, 设置tomcat配置文件,在My ...

  9. php 单进程SAPI生命周期

    php的生命周期3.1 STARTUP    1.初始化引擎和核心组件.    2.解析php.ini.    3.初始化静态构建的模块(MINIT).    4.初始化共享模块(MINIT).3.2 ...

  10. [Webpack] Create Separate webpack Configs for Development and Production with webpack-merge

    The development and production modes in webpack optimize the output in different ways. In developmen ...