一
1 vector表示一段连续的内存区域,每个元素被顺序存储在这段内存中。对vector的随机访问效率很高。
删除vector的任一元素而不是末尾的元素效率比较低
list表示非连续的内存区域,并通过一对指向首尾元素的指针双向连接起来,从而允许向前向后两个方向进行遍历。
a 如果我们需要随机访问一个容器,则vector要比list好
b 如果我们已知要存储元素的个数,则vector要比list好
c 如果我们需要的不只是在容器两端插入和删除元素,则list要比vector好
d 除非我们需要在容器首部插入和删除元素,否则vector要比deque好
2 容量是指在容器下一次需要增长自己之前能够被加入到容器中的元素总数(容量至于连续存储的容器相关,例如
vector,deque,string)。为了知道一个容器的容量,我们调用它的capacity()函数,而长度是指容器当前拥有元素的个数。为了获
得容器的当前长度,我们调用它的size()操作。
对于小的数据类型,vector的性能要比list好得多,对于大型的数据类型则相反,list的性能要好得多。区别是由于vector需要重
新增长以及拷贝元素。但是数据类型的长度不是影响容器性能的唯一标准,数据类型的复杂性也会影响到元素插入的性能。
无论是list还是vector,对于已定义构造函数的类来说,插入这样的类的元素都需要调用拷贝构造函数。简单类对象和大型简单类
对象通过按位拷贝插入,而string类对象和大型复杂类对象通过调用拷贝构造函数来插入。
reserve()操作允许程序员将容器的容量设置成一个显式指定的值。
二 定义一个顺序容器
#include<vector>
#include<list>
#include<deque>
#include<map>
#include<set>
容器对象的定义以容器类型的名字开始,后面是所包含的元素的实际类型,例如:
vector<string> svec;
list<int> ilist;
if(svec.empty()!=true)//判断容器是否为空
svec.push_back(text_word);//将元素text_word插入到容器的尾部
list和deque容器也支持push_front(),它把新元素插入在链表的前端
3 vector.resize与vector.reserve的区别
a reserve是容器预留空间,但并不真正创建元素对象,在创建对象之前,不能引用容器内的元素,因此当加入新的元素时,需要用
push_back()/insert()函数。
b resize是改变容器的大小,并且创建对象,因此,调用这个函数之后,就可以引用容器内的对象了,因此当加入新的元素时,用
operator[]操作符,或者用迭代器来引用元素对象。
三 迭代器
1 迭代器(iterator)提供了一种一般化的方法,对顺序或关联容器类型中的每个元素进行连续访问。
每个容器类型都提供一个begin()和一个end()成员函数。
begin()返回一个iterator,它指向容器的第一个元素
end()返回一个iterator,它指向容器末尾元素的下一个位置
为了迭代任意容器类型的元素我们可以这样写
for ( iter = container.begin();
	iter != container.end(); ++iter )
	do_something_with_element( *iter );
2 除了iterator类型,每个容器还定义了一个const iterator类型,后者对于遍历const容器时必需的,const iterator允许以只读
方式访问容器的底层元素。
vector<int>::const_iterator c_iter;
vector<int>::iterator iter = vec.begin()+vec.size()/2;	//将iter 指向vec 的中间元素
iter += 2;	//将iter 向前移动两个元素
iterator 算术论算只适用于vector 或deque 而不适用于list 因为list 的元素在内存中不是连续存储.
3 定义一个vector
vector<string> svec2(svec.begin(),svec.end())
除了一对iterator 之外两个指向内置数组的指针也可以被用作元素范围标记器:
#include <string>
string words[4] = {
"stately", "plump", "buck", "mulligan"
};
vector< string > vwords( words, words+4 );
四 顺序容器操作
1 查找并插入find() insert()
a
string son("Danny");
list<string>::iterator iter;
iter=find(slist.begin(),slist.end(),son);
slist.insert(iter,spouse);
slist.insert( slist.end(), value );等价于slist.push_back(value);
b insert()方法的第二种形式支持在某个位置插入指定数量的元素.
vector<string> svec;
....
string anna("Anna");
svec.insert(svec.begin(),10,anna);
c insert()方法的最后一种形式支持向容器插入一段范围内的元素.
string sarray[4] = { "quasi", "simba", "frollo", "scar" };
svec.insert( svec.begin(), sarray, sarray+4 );
svec.insert( svec.begin() + svec.size()/2,
sarray+2, sarray+4);
2 删除操作 erase()
删除容器内元素的一般形式是一对erase()方法一个删除单个元素另一个删除由一对iterator 标记的一段范围内的元素.
删除容器末元素的简短方法由pop_back()方法支持。
a slist.erase(iter);
b slist.erase(slist.begin(),slist.end());
3 赋值和对换
// slist1 含有10 个元素
// slist2 含有24 个元素
// 赋值之后都含有24 个元素
slist1 = slist2;
swap()可以被看作是赋值操作符的互补操作当我们写
slist1.swap( slist2 );
时slist1 现在含有24 个string 元素是用string 赋值操作符拷贝的就如同我们写
slist1 = slist2;
一样。
两者的区别在于,slist2 现在含有slist1 中原来含有的10 个元素的拷贝。如果两个容器的长度不同,则容器的长度就被重新设置
,且等于被拷贝容器的长度。
4 泛型算法
从概念上讲,我们的思想是把所有容器类型的公共操作抽取出来,形成一个通用算法集合,它能够被应用到全部容器类型以及内置
数组类型上,这组通用算法被称作泛型算法。
泛型算法通过一个iterator对,被绑定到一个特殊的容器上。
#include <list>
#include <vector>
int ia[ 6 ] = { 0, 1, 2, 3, 4, 5 };
vector<string> svec;
list<double> dlist;
// the associated header file
#include <algorithm>
vector<string>::iterator viter;
list<double>::iterator liter;
int *pia;
// 如果找到, find()返回指向该元素的iterator
// 对于数组, 返回指针
pia = find( &ia[0], &ia[6], some_int_value );
liter = find( dlist.begin(), dlist.end(), some_double_value );
viter = find( svec.begin(), svec.end(), some_string_value );
五 存储文本行
怎样获得文本的每一行呢?标准库支持getline()函数声明如下
istream& getline( istream &is, string str, char delimiter );
getline()读取istream 对象,向string 对象插入字符,包括空格,直到遇到分割符、文件结束,或者被读入的字符序列等于
string 对象的max_size()值,在该点处读入操作失败。
1 找到一个字串
string 类提供了一套查找函数,都以find 的各种变化形式命名。find()是最简单的实例;给出一个字符串,它返回匹配子串的第
一个字符的索引位置。或者返回一个特定的值:
string::npos
表明没有匹配
例如:
#include <string>
#include <iostream>
int main() {
string name( "AnnaBelle" );
int pos = name.find( "Anna" );
if ( pos == string::npos )
cout << "Anna not found!\n";
else cout << "Anna found at pos: " << pos << endl;
}
虽然返回的索引类型差不多总是int 类型但是更严格的可移植的正确声明应该使
用以下形式
string::size_type
来保存从find()返回的索引值例如
string::size_type pos = name.find( "Anna" );
find_first_of()查找与被搜索字符串中任意一个字符相匹配的第一次出现,并返回它的索引位置。例如,下列代码找到字符串中的
第一个数字:
#include <string>
#include <iostream>
int main() {
string numerics( "0123456789" );
string name( "r2d2" );
string::size_type pos = name.find_first_of( numerics );
cout << "found numeric at index: "
<< pos << "\telement is "
<< name[pos] << endl;
}
在这个例子中,pos 被设置为1。
我们可以通过给出第二个参数来实现这个参数指明了字符串中起始查找位置的索引。
// ok: 被改正之后的循环迭代
while (( pos = name.find_first_of( numerics, pos ))
!= string::npos )
{
cout << "found numeric at index: "
<< pos << "\telement is "
<< name[pos] << endl;
// 移到被找到元素的后一位置
++pos;
}
查找一个单词
// 程序片断
// pos: 单词后一位置的索引
// prev_pos: 单词开始的索引
string::size_type pos = 0, prev_pos = 0;
while (( pos = textline.find_first_of( ' ', pos ))
!= string::npos )
{
// 对 string 进行一些操作
// 调整位置标记器
prev_pos = ++pos;
}
对于循环的每次迭代prev_pos 索引单词的开始pos 持有单词末尾的下一个位置空
格的位置然后每个被标识的单词的长度为
pos - prev_pos; // 标识单词长度
substr()操作生成现有string 对象的子串的一个拷贝。它的第一个参数指明开始的位置,第二个可选的参数指明子串的长度,如果
省略第二个参数将拷贝字符串的余下部分。
find()
rfind()
find_first_not_of()
find_last_of()
find_last_not_of()
六 关联容器
在使用map时,两个最主要的动作是向里面放入元素,以及查询元素是否存在。
定义map: map<string, int> word_count;
当我们写如下语句时
word_count[ string("Anna") ] = 1;
将发生以下事情:
1 一个未命名的临时string 对象被构造并传递给与map 类相关联的下标操作符,这个对象用Anna 初始化
2 在word_count 中查找Anna,项没有找到.
3 一个新的键/值对被插入到word_count 中.当然,键是一个string 对象持有Anna。但是值不是1 而是0
4 插入完成接着值被赋为1
通过下标操作符把一个键插入到map 中时,而相关联的值被初始化为底层元素类型的缺省值。内置数值类型的缺省值为0
一种常用的插入单个元素的方法如下:
word_count.insert(
map<string,int>::value_type(string("anna"),1));
typedef map<string,int>::value_type valType;
另外一种版本的inset()
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< string, int > word_count_two( word_count );
2 查找并获取map中的元素
a int count=word_count["wrinkles"];
当map中存在这条记录时,表现正常。如果不存在这样的记录,使用下表操作符会引起插入一条记录。
b int count=0
  if(word_cout.cout("wrinkles"))
	count=word_count["wrinkles"];
c int count=0;
  map<string,int>::iterator it=word_cout.find("wrinkles");
  if(it!=word_count.end())
	cout=(*it).second;
指向map 中元素的iterator 指向一个pair对象其中first,拥有键second 拥有值.
3 从map中删除元素
a 删除一个独立的元素,传递给erase()一个键值或iterator
b 删除一列元素,我们传递给erase()一对iterator
七 创建单词排除集
1 定义set并放入元素
#include<set>
set<string> exculusion_set;
a exculusion_set.insert("the");
b 通过向insert()提供一对iterator以便插入一个元素序列。
2 搜索一个元素
查询set对象中是否存在一个值的两个操作是find()和count()。如果元素存在,则find()返回指向这个元素的iterator,否则返回
一个等于end()的iterator,表示该元素不存在。如果找到元素,count()返回1,如果元素不存在,则返回0。
八 multimap和multiset
#include<map>
multimap<key_type,value_type> multimapName;
#include <map>
#include <string>
void code_fragment()
{
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()。
#include <map>
#include <string>
#include <utility>
void code_fragment()
{
multimap< string, string > authors;
// ...
string search_item( "Haruki Murakami" );
while ( cin && cin >> search_item )
switch ( authors.count( search_item ))
{
// 不存在, 继续往下走
case 0:
break;
// 只有一项, 使用普通的find()操作
case 1: {
multimap< string,string >::iterator iter;
iter = authors.find( search_item );
// do something with element
break;
}
// 出现多项 ...
default:
{
typedef multimap< string,string >::iterator iterator;
pair< iterator, iterator > pos;
// pos.first 指向第一个出现
// pos.second 指向值不再出现的位置
pos = authors.equal_range( search_item );
for ( ; pos.first != pos.second; pos.first++ )
// 对每个元素进行操作
}
}
}
九 栈
#include<stack>
empty() 如果栈为空,则返回true,否则返回false
size() 返回栈中元素的个数
pop() 删除,但不返回栈顶元素
top() 返回,但不删除栈顶元素
push(item) 放入新的栈顶元素
stack<int> intstack;
栈类型被称为容器适配器,因为他把栈抽象施加在底层容器集上、缺省情况下,栈用容器了性deque实现,因为deque为容器前段的
插入和删除提供了有效的支持。
一种取代的存储策略是定义一个指
针栈例如
#include <stack>
class NurbSurface { /* mumble */ };
stack< NurbSurface* > surf_Stack;
FIFO队列(queue) 优先级队列(priority_queue)
empty() 如果队列为空,则返回true,否则返回false
size() 返回队列中元素的个数
pop() 删除,但不返回队首元素
front() 返回,但不删除队首元素
back() 返回,但不删除队尾元素
top() 返回,但不删除priotity_queue的优先级最高的元素,只能应用在priority_queue上
push(item) 在队尾放入一个新元素
 
                    
                     
                    
                 
                    
                 
 posted on
 posted on 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号