一般地当我们只想知道一个值是否存在时,set 最有用处;希望存储也可能修改一个相关的值时,map 最为有用.
在map(也叫关联数组)中我们提供一个键/值对,键用来索引ma,而值用作被存储和检索的数据.
#include <map>
在使用map和set时两个最主要的动作是向里面放入元素以及查询元素是否存在.
定义并生成
map
为定义map对象我们至少要指明键和值的类型例如
map<string, int> word_count;
class employee;
map<int, employee*> personnel;
定义了map 以后下一步工作就是加入键/
值元素对
word_count[ string("Anna") ] = 1;
1一个未命名的临时string 对象被构造并传递给与map 类相关联的下标操作符,这个对象用Anna 初始化,
2 在word_count 中查找Anna 项,没有找到
3 一个新的键/值对被插入到word_count 中。当然键是一个string对象持有“Anna”。但是值不是1 而是0
4 插入完成接着值被赋为1
用下标操作符把map 初始化至一组元素集合,会使每个值都被初始化为缺省值。然后再被赋值为显式的值,如果元素是类对象而且它的缺省初始化和赋值的运算量都很大。就会影响程序的性能
word_count.insert(
map<string,int>::value_type( string("Anna"), 1 )
);
其作用是创建一个pair对象,接着将其直接插入map
typedef map<string,int>::value_type valType;
word_count.insert( valType( string("Anna"), 1 ));
为插入一定范围内的键/值元素,我们可以用另一个版本的insert()方法。它用一对iterator作为参数。
map< string, int > word_count;
// ... fill it up
map< string, int > word_count_two;
// 插入所有键/值对
word_count_two.insert(word_count.begin(),word_count.end());
查找并获取map
中的元素。
下标操作符给出了获取一个值的最简单方法例如
// map<string,int> word_count;
int count = word_count[ "wrinkles" ];
但是只有当map 中存在这样一个键的实例时该代码才会表现正常如果不存在这样
的实例使用下标操作符会引起插入一个实例在本例中键/值对
string( "wrinkles" ), 0
被插入到word_count 中count 被初始化为0
有两个map 操作能够发现一个键元素是否存在而且在键元素不存在时也不会引起插入实例
1 Count(keyValue)
count()返回map 中keyValue 出现的次数当然对于map
而言返回值只能是0 或1 如果返回值非0 我们就可以安全地使用下标操作符例如
int count = 0;
if ( word_count.count( "wrinkles" ))
count = word_count[ "wrinkles" ];
2 Find(keyValue) 如果实例存在则find()返回指向该实例的iterator 如果不存在
则返回等于end()的iterator 例如
int count = 0;
map<string,int>::iterator it = word_count.find( "wrinkles" );
if ( it != word_count.end() )
count = (*it).second;
指向map中元素的iterator指向一个pair对象其中first拥有键,second拥有值
对map
进行迭代
我们可以通过对由begin()和end()两个迭代器标记的所有元素进行迭代来做到这一点。
typedef map<string,int> tmap;
tmap::iterator iter = text_map->begin(),
iter_end = text_map->end();
while ( iter != iter_end )
{ cout << "word: " << (*iter).first << " ("<<(*iter).second<<")";
从map 中删除元素的erase()操作有三种变化形式。为了删除一个独立的元素我们传递
给erase()一个键值或iterator, 为了删除一列元素我们传递给erase()一对lieator。
一个map 只能拥有一个键值的惟一实例,为了给同一个键提供多个项我们必须使用multimap
定义set
并放入元素
set<string> exclusion_set;
用insert 操作将单个元素插入到set 中例如
exclusion_set.insert( "the" );
exclusion_set.insert( "and" );
我们可以通过向insert()提供一对iterator 以便插入一个元素序列
搜索一个元素
查询set 对象中是否存在一个值的两个操作是find()和count() 如果元素存在则find()
返回指向这个元素的iterator 否则返回一个等于end()的iterator 表示该元素不存在如果
找到元素count()返回1 如果元素不存在则返回0
迭代一个set
对象
set< short > occurrence_lines;
loc::iterator liter = ploc->begin(),
liter_end = ploc->end();
while ( liter != liter_end ) {
occurrence_lines.insert( occurrence_lines.end(),
(*liter).first );
++liter;
}
multimap
和multiset
#include <map>
multimap< key_type, value_type > multimapName;
multimap< string, list< string > > synonyms;
#include <set>
multiset< type > multisetName;
对于multimap 或multiset ,一种迭代策略是联合使用由find()返回的iterator (指向第一个实例)和由count()返回的值.这样做能奏效因为我们可以保证实例在容器中是连续出现的。
multimap< string, string > authors;
string search_item( "Alain de Botton" );
// ...
int number = authors.count( search_item );
multimap< string,string >::iterator iter;
iter = authors.find( search_item );
for ( int cnt = 0; cnt < number; ++cnt, ++iter )
do_something( *iter );
更精彩的策略是使用由multiset 和multimap 的特殊操作equal_range()返回的iterator 对值.如果这个值存在,则第一个iterator 指向该值的第一个实例。且第二个iterator 指向这个值的最后实例的下一位置。如果最后的实例是multiset 的末元素,则第二个iterator 等于end()。
插入和删除操作与关联容器set 和map 相同equal_range()可以用来提供iterator 对以
便标记出要被删除的多个元素的范围
栈容器
在程序执行过程中可能动态出现多个嵌套状态时
操作 |
功能 |
|||
empty()
|
如果栈为空 |
则返回true |
否则返回false |
|
size()
|
返回栈中元素的个数 |
|
||
pop()
|
删除 |
但不返回栈顶元素 |
|
|
top()
|
返回 |
但不删除栈顶元素 |
|
|
push(item)
|
放入新的栈顶元素 |
|
||
#include <stack>
#include <iostream>
int main()
{
const int ia_size = 10;
int ia[ia_size ] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
// 填充 stack
int ix = 0;
stack< int > intStack;
for ( ; ix < ia_size; ++ix )
intStack.push( ia[ ix ] );
int error_cnt = 0;
if ( intStack.size() != ia_size ) {
cerr << "oops! invalid intStack size: "
<< intStack.size()
<< "/t expected: " << ia_size << endl;
++error_cnt;
}
int value;
while ( intStack.empty() == false )
{
// 读取栈顶元素
value = intStack.top();
if ( value != --ix ) {
cerr << "oops! expected " << ix
<< " received " << value
<< endl;
++error_cnt;
}
// 弹出栈顶元素, 并重复
intStack.pop();
}
cout << "Our program ran with "
<< error_cnt << " errors!" << endl;
}
缺省情况下栈用容器类型deque 实现因为deque
为容器前端的插入和删除提供了有效支持而vector 则不.
stack< int, list<int> > intStack;
队列
queue
先进先出的存储和检索策略
FIFO 队列就称作queue 以及priority_queue 优先级队列
#include <queue>
deque .实现因为deque
为容器前端的插入和删除提供了有效支持,而vector 则不.stack< int, list<int> > intStack;
操作 |
功 |
能 |
||||||||||
empty()
|
如果队列为空 |
则返回true |
否则返回false |
|||||||||
size()
|
返回队列中元素的个数 |
|
||||||||||
pop()
|
删除但不返回队首元素 |
在priority_queue 中 |
队首元素代表优先级最 |
|||||||||
|
高的元素 |
|
|
|||||||||
front()
|
返回 |
但不删除队首元素 |
它只能应用在一般队列上 |
|||||||||
back()
|
返回 |
但不删除队尾元素 |
它只能应用在一般队列上 |
|||||||||
top()
|
返回但不删除priority_queue 上 |
priority_queue
|
的优先级最高的元素 |
只能应用在 |
||||||||
push(item)
|
在队尾放入一个新元素 |
对于priority_queue |
将根据优先级排序 |
|||||||||