一、容器适配器
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. AR(Average Recall, 平均查全率), ANMRR(Average Normalized Modified Retrieval Rate, 平均归一化检索秩)

    AR(Average Recall, 平均查全率), ANMRR(Average Normalized Modified Retrieval Rate, 平均归一化检索秩)

  2. How to make a combo box with fulltext search autocomplete support?

    I would like a user to be able to type in the second or third word from a TComboBoxitem and for that ...

  3. LwIP buffer management, memory configuration options

    http://www.st.com/st-web-ui/static/active/cn/resource/technical/document/application_note/DM00036052 ...

  4. 畅通工程_hdu_1232(并查集)

    畅通工程 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  5. HttpClient post提交数据,汉字转码

    public static String post(String url, String data) throws ClientProtocolException, IOException { Htt ...

  6. Source Insight 源代码查看工具

    在开发的过程中,有时候我们需要研究源代码,查看源码是一个好的习惯,能帮我们学到很多的东西,比如JDK可以帮助我们理解很多设计模式在实际开发中的应用,又或者android开发者,源代码更是必不可少的,当 ...

  7. 《iOS应用逆向工程:分析与实战》

    <iOS应用逆向工程:分析与实战> 基本信息 作者: 沙梓社    吴航    刘瑾 丛书名: 信息安全技术丛书 出版社:机械工业出版社 ISBN:9787111450726 上架时间:2 ...

  8. jenkins的docker

    参考:https://store.docker.com/images/jenkins?tab=description https://my.oschina.net/jayqqaa12/blog/633 ...

  9. Hibernate查询语言

    HQL(Hibernate Query Language)查询语言是完全面向对象的查询语言,它提供了更加面向对象的封装,它可以理解如多态.继承和关联的概念.HQL看上去和SQL语句相似,但它却提供了更 ...

  10. 使用C# + httpWebRequest 解析WMTS服务元数据

    解析http://219.142.81.86/igserver/ogc/kvp/TAS10R52000J49/WMTSServer服务的元数据 // 测试httpWebRequest读取 wmts元数 ...