文档章节

stl 容器适配器、迭代器适配器和函数适配器讲解

清风伴月
 清风伴月
发布于 2017/04/01 15:04
字数 1381
阅读 127
收藏 0

 

一、迭代器

list的迭代器不支持算术运算,也不支持关系运算符(<=,<,>=,>),他只提供前置和后置的自增、自减以及相等和不相等运算。list的内存不连续。

vector和deque容器的迭代器是一种类型,vector能做的DEQUE也可以。

二、容器适配器

queue,priority_queue,stack.

默认的queue和stack实在deque基础上实现,而PRIORITY_QUEUE则是在vector基础上实现。

queue需要提供PUSH_FRONT函数,只能由deque和list初始化。

stack可以由vector,deque,list初始化。

priority_queue需要提供随即访问功能,由vector和deque初始化。

在优先队列中,优先级高的元素先出队列。
标准库默认使用元素类型的<操作符来确定它们之间的优先级关系。
优先队列的第一种用法,也是最常用的用法:

priority_queue<int> qi;

通过<操作符可知在整数中元素大的优先级高。
故示例1中输出结果为:9 6 5 3 2

第二种方法:
在示例1中,如果我们要把元素从小到大输出怎么办呢?
这时我们可以传入一个比较函数,使用functional.h函数对象作为比较函数。

priority_queue<int, vector<int>, greater<int> >qi2;

其中
第二个参数为容器类型。
第二个参数为比较函数。greater是内部函数,也可以less
故示例2中输出结果为:2 3 5 6 9

第三种方法:
自定义优先级。

struct node
 {
     friend bool operator< (node n1, node n2)
     {
         return n1.priority < n2.priority;
     }
     int priority;
     int value;
 };

在该结构中,value为值,priority为优先级。
通过自定义operator<操作符来比较元素中的优先级。
在示例3中输出结果为:
优先级  值
9         5
8         2
6          1
2          3
1          4
但如果结构定义如下:

struct node
 {
     friend bool operator> (node n1, node n2)
     {
         return n1.priority > n2.priority;
     }
     int priority;
     int value;
 };

则会编译不过(G++编译器)
因为标准库默认使用元素类型的<操作符来确定它们之间的优先级关系。
而且自定义类型的<操作符与>操作符并无直接联系,故会编译不过。

//代码清单

 

#include<iostream>
 #include<functional>
 #include<queue>
using namespace std;
 struct node
 {
     friend bool operator< (node n1, node n2)
     {
         return n1.priority < n2.priority;
     }
     int priority;
     int value;
 };
 int main()
 {
     const int len = 5;
     int i;
     int a[len] = {3,5,9,6,2};
     //示例1
     priority_queue<int> qi;
     for(i = 0; i < len; i++)
         qi.push(a[i]);
     for(i = 0; i < len; i++)
     {
         cout<<qi.top()<<" ";
         qi.pop();
     }
     cout<<endl;
     //示例2
     priority_queue<int, vector<int>, greater<int> >qi2;
     for(i = 0; i < len; i++)
         qi2.push(a[i]);
     for(i = 0; i < len; i++)
     {
         cout<<qi2.top()<<" ";
         qi2.pop();
     }
     cout<<endl;
     //示例3
     priority_queue<node> qn;
     node b[len];
     b[0].priority = 6; b[0].value = 1; 
     b[1].priority = 9; b[1].value = 5; 
     b[2].priority = 2; b[2].value = 3; 
     b[3].priority = 8; b[3].value = 2; 
     b[4].priority = 1; b[4].value = 4; 

     for(i = 0; i < len; i++)
         qn.push(b[i]);
     cout<<"优先级"<<'\t'<<"值"<<endl;
     for(i = 0; i < len; i++)
     {
         cout<<qn.top().priority<<'\t'<<qn.top().value<<endl;
         qn.pop();
     }
     return 0;
 }
 

C++之函数适配器

C++定义了一些特殊的函数适配器(Function adapters),通过这些函数适配器我们可以将预先定义的仿函数和其他数值结合在一起或使用特殊情况。

上例子吧:

void testAdapter()
{
    std::set<int,std::greater<int> > intSet;
    std::deque<int> intDeque;

    for(int i=1;i<10;++i)
        intSet.insert(i);
    std::cout<<"Initialized Set:\n";
    copy(intSet.begin(),intSet.end(),
         std::ostream_iterator<int>(std::cout," "));
    transform(intSet.begin(),intSet.end(),
              back_inserter(intDeque),
             bind2nd(std::multiplies<int>(),10));  ///operation
    std::cout<<"\nDeque data:\n";
    copy(intDeque.begin(),intDeque.end(),
         std::ostream_iterator<int>(std::cout," "));

    replace_if(intDeque.begin(),intDeque.end(),
               bind2nd(std::equal_to<int>(),70),  ///operation
               0);
    std::cout<<"\nDeque data after replace:\n";
    copy(intDeque.begin(),intDeque.end(),
         std::ostream_iterator<int>(std::cout," "));
    intDeque.erase(remove_if(intDeque.begin(),intDeque.end(),
                             bind2nd(std::less<int>(),50)),
                   intDeque.end());
    std::cout<<"\nDeque data after erase:\n";
    copy(intDeque.begin(),intDeque.end(),
         std::ostream_iterator<int>(std::cout," "));
}

函数适配器bind2nd的工作原理:

以    transform(intSet.begin(),intSet.end(),
              back_inserter(intDeque),
              bind2nd(std::multiplies<int>(),10));  ///operation

为例吧:

   transform()希望自己的第四个参数是一个能接纳单一参数(即容器实际元素)的表达式,
   然后我们希望先将元素乘以10再传给transform(),
   所有我们必须购置一个表达式,接受两个参数,并以数值10作为第二个参数
   以此产生一个只接受一个参数的表达式

   bind2nd会把表达式保存起来,将第二个参数当内部数值保存起来
   当算法以实际集群元素为参数,调用bind2nd时,bind2nd将元素作为第一参数
   把原先保存下来的数值作为第二个参数,调用保留下来的表达式,并返回调用结果

   详见《源源码剖析》第8章

 

另外,某些仿函数可以用来调用集群内每个元素的成员函数:
for_each(intDeque.begin(),intDeque.end(),
         mem_fun_ref(&Person::printInfo()))
仿函数mem_fun_ref将调用它所作用的每个元素的某个成员函数
当然,必须保证这些元素的类型是Person或者Person的派生类,
并且可以printInfo()函数

 

STL的stack适配器函数

  

c.push(const value_type&v)

将v压入到栈中

c.pop()

移除栈顶元素

c.top()

返回栈顶元素

c.empty()

栈空时返回true

c.size()

返回栈中的元素个数

== 和 <

判等运算符和按字典顺序计算的小于运算符

 

STL的queue适配器函数

 

c.push(const value_type&v)

将v放到队列尾部

c.pop()

从队列前端移除元素

c.front()

返回队列前端元素

c.back()

返回队列尾部元素

c.empty()

队列空时返回true

c.size()

返回队列的元素个数

== 和 <

判等运算符和按字典顺序计算的小于运算符

© 著作权归作者所有

清风伴月
粉丝 1
博文 129
码字总数 255659
作品 0
海淀
程序员
私信 提问
STL入门导论[原+译]

STL入门引导 涉及到的源码:http://download.csdn.net/detail/nuptboyzhb/4239649 STL主要有以下六个大的部分: l 迭代器(iterators) 迭代器可以理解为一个模板指针;迭代器技术能够使程序...

长平狐
2012/10/08
129
0
C++ STL编程轻松入门 5

2.2.3 第三版:唯美主义的杰作   事态的发展有时候总会趋向极端,这在那些唯美主义者当中犹是如此。首先声明,我并不是一个唯美主义者,提供第二版程序的改进版,完全是为了让你更深刻的感...

暖冰
2015/11/21
50
0
C++语言学习之STL 的组成

STL有三大核心部分:容器(Container)、算法(Algorithms)、迭代器(Iterator),容器适配器(container adaptor),函数对象(functor),除此之外还有STL其他标准组件。通俗的讲: 容器:装...

杨坤乾
2014/02/11
684
0
C++ STL学习——vector

学过C++的人肯定会很熟悉STL标准模板库,STL其实就是封装了一系列的接口,供我们调用。很多函数或者算法的实现不需要我们从头开始写,大大提高我们的编程效率。这篇博客在简单介绍STL的情况下...

chenyufeng1991
2016/08/21
0
0
ICE第二篇--一个"hello world"的简单例子

1 本文介绍一个hello world输出的例子。 ice应用的步骤如下: 编写 Slice 定义并编译它。 编写服务器并编译它。 编写客户并编译它。 基本框架图示: 本文代码图示: 需要注意的概念: servan...

moki_oschina
2018/06/06
31
0

没有更多内容

加载失败,请刷新页面

加载更多

《Designing.Data-Intensive.Applications》笔记 四

第九章 一致性与共识 分布式系统最重要的的抽象之一是共识(consensus):让所有的节点对某件事达成一致。 最终一致性(eventual consistency)只提供较弱的保证,需要探索更高的一致性保证(stro...

丰田破产标志
今天
6
0
docker 使用mysql

1, 进入容器 比如 myslq1 里面进行操作 docker exec -it mysql1 /bin/bash 2. 退出 容器 交互: exit 3. mysql 启动在容器里面,并且 可以本地连接mysql docker run --name mysql1 --env MY...

之渊
今天
7
0
python数据结构

1、字符串及其方法(案例来自Python-100-Days) def main(): str1 = 'hello, world!' # 通过len函数计算字符串的长度 print(len(str1)) # 13 # 获得字符串首字母大写的...

huijue
今天
5
0
OSChina 周日乱弹 —— 我,小小编辑,食人族酋长

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @宇辰OSC :分享娃娃的单曲《飘洋过海来看你》: #今日歌曲推荐# 《飘洋过海来看你》- 娃娃 手机党少年们想听歌,请使劲儿戳(这里) @宇辰OSC...

小小编辑
今天
1K
11
MongoDB系列-- SpringBoot 中对 MongoDB 的 基本操作

SpringBoot 中对 MongoDB 的 基本操作 Database 库的创建 首先 在MongoDB 操作客户端 Robo 3T 中 创建数据库: 增加用户User: 创建 Collections 集合(类似mysql 中的 表): 后面我们大部分都...

TcWong
今天
40
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部