【C++ Primer 学习笔记】: 容器和算法之【顺序容器】

原创 2015年11月17日 15:59:30

本系列博客主要是在学习 C++ Primer 时的一些总结和笔记。
【C++ Primer 学习笔记】: 容器和算法之【顺序容器】
本文地址:http://blog.csdn.net/shanglianlm/article/details/49888699

顺序容器

这里写图片描述

1 定义

头文件

#include <vector>
#include <list>
#include <deque>

1-1 初始化

这里写图片描述

接受容器大小做形参的构造函数只适用于顺序容器,而关联容器不支持这种初始化。

1-2 容器内元素的类型约束

C++ 语言中,大多数类型都可用作容器的元素类型。容器元素类型必须满足以下两个约束:
• 元素类型必须支持赋值运算。
• 元素类型的对象必须可以复制。

引用不支持一般意义的赋值运算,因此没有元素是引用类型的容器。

除输入输出(IO)标准库类型之外,所有其他标准库类型都是有效的容器元素类型。

容器的容

// note spacing: use ">>" not ">>" when specifying a container element type 
vector< vector<string> > lines; // vector of vectors

2 迭代器和迭代器范围

2-1 迭代器操作

这里写图片描述

vector 和 deque 容器的迭代器提供额外的运算

这里写图片描述

2-2 迭代器范围

左闭合区间
这里写图片描述
这里写图片描述

3 顺序容器的操作

3-1 容器定义的类型别名

这里写图片描述

3-2 begin 和 end 成员

这里写图片描述

3-3 顺序容器中添加元素

这里写图片描述

避免存储 end 操作返回的迭代器
不要存储 end 操作返回的迭代器。添加或删除 deque 或 vector 容器内的元素都会导致存储的迭代器失效。

导致死循环的错误示例

例如,考虑一个读取容器中每个元素的循环,对读出元素做完处理后,在原始元素后面插入一个新元素。

vector<int>::iterator first = v.begin(), last = v.end(); // cache end iterator 
     // diaster: behavior of this loop is undefined 
while (first != last) { 
       // do some processing 
       // insert new value and reassign first, which otherwise would be invalid 
      first = v.insert(first, 42); 
      ++first; // advance first just past the element we added 
} 

为了避免存储 end 迭代器,可以在每次做完插入运算后重新计算 end 迭代器值:

// safer: recalculate end on each trip whenever the loop adds/erases elements 
while (first != v.end()) { 
   // do some processing 
   first = v.insert(first, 42); // insert new value 
   ++first; // advance first just past the element we added 
} 

3-4 关系操作符

C++ 语言只允许两个容器做其元素类型定义的关系运算。
所有容器都通过比较其元素对来实现关系运算: ivec1 < ivec2

假设 ivec1 和 ivec2 都是 vector 类型的容器,则上述比较使用了内置 int 型定义的小于操作符。如果这两个 vector 容器存储的是 strings 对象,则使用 string 类型的小于操作符。

如果上述 vector 容器存储 Sales_item 类型的对象,则该比较运算不合法。因为 Sales_item 类型没有定义关系运算,所以不能比较存放 Sales_items 对象的容器:

3-5 容器大小的操作

这里写图片描述

3-6 访问元素

这里写图片描述

// check that there are elements before dereferencing an iterator or calling front or back 
if (!ilist.empty()) { 
    // val and val2 refer to the same element 
   list<int>::reference val = *ilist.begin(); 
   list<int>::reference val2 = ilist.front(); 
   // last and last2 refer to the same element 
   list<int>::reference last = *--ilist.end(); 
   list<int>::reference last2 = ilist.back(); 
} 

3-7 删除元素

这里写图片描述

3-8 赋值与 swap

这里写图片描述

赋值和 assign 操作使左操作数容器的所有迭代器失效。swap 操作则不会使迭代器失效。完成 swap 操作后,尽管被交换的元素已经存放在另一容器中,但迭代器仍然指向相同的元素。

由于 assign 操作首先删除容器中原来存储的所有元素,因此,传递给 assign 函数的迭代器不能指向调用该函数的容器内的元素。

带有一对迭代器参数的 assign 操作允许我们将一个容器的元素赋给另一个不同类型的容器。

关于 swap 的一个重要问题在于:该操作不会删除或插入任何
元素,而且保证在常量时间内实现交换。由于容器内没有移动
任何元素,因此迭代器不会失效。

4 vector容器的自增长

4-1 capacity 和 reserve 成员

vector 类提供了两个成员函数:capacity 和 reserve 使程序员可与 vector 容器内存分配的实现部分交互工作。capacity 操作获取在容器需要分配更多的存储空间之前能够存储的元素总数,而 reserve 操作则告诉 vector 容器应该预留多少个元素的存储空间。

size 和 capacity 的区别:
size 指容器当前拥有的元素个数;
capacity 则指容器在必须分配新存储空间之前可以存储的元素总数。

5 容器的选用

通常来说,除非找到选择使用其他容器的更好理由,否则 vector 容器都是最佳选择。

这里写图片描述

6 容器适配器

这里写图片描述

头文件

#include <stack>
#include <queue>

默认的 stack 和 queue 都基于 deque 容器实现,而 priority_queue 则在 vector 容器上实现。在创建适配器时,通过将一个顺序容器指定为适配器的第二个类型实参,可覆盖其关联的基础容器类型:

// empty stack implemented on top of vector 
stack< string, vector<string> > str_stk; 
// str_stk2 is implemented on top of vector and holds a copy of svec 
stack<string, vector<string> > str_stk2(svec);

对于给定的适配器,其关联的容器必须满足一定的约束条件。stack 适配器所关联的基础容器可以是任意一种顺序容器类型。
因此,stack 栈可以建立在 vector、list 或者 deque 容器之上。
而 queue 适配器要求其关联的基础容器必须提供 push_front 运算,因此只能建立在 list 容器上,而不能建立在 vector 容器上。
priority_queue 适配器要求提供随机访问功能,因此可建立在 vector 或 deque 容器上,但不能建立在 list 容器上。

6-1 栈适配器

这里写图片描述

实例

// number of elements we'll put in our stack 
const stack<int>::size_type stk_size = 10; 
stack<int> intStack; // empty stack 
// fill up the stack 
int ix = 0; 
while (intStack.size() != stk_size) 
  // use postfix increment; want to push old value onto intStack 
  intStack.push(ix++); // intStack holds 0...9 inclusive
int error_cnt = 0; 
// look at each value and pop it off the stack 
while (intStack.empty() == false) { 
  int value = intStack.top(); 
  // read the top element of the stack 
  if (value != --ix) { 
         cerr << "oops! expected " << ix 
         << " received " << value << endl; 
         ++error_cnt; 
         } 
 intStack.pop(); // pop the top element, and repeat 
} 
cout << "Our program ran with " 
<< error_cnt << " errors!" << endl; 

声明语句:

stack<int> intStack; // empty stack 

6-2 队列和优先级队列

这里写图片描述

版权声明:本文为博主原创文章,欢迎转载,转载请注明出处。

C++primer第九章习题解答

练习9.1:对于下面的程序任务,vector、deque和list哪种容器最为适合?解释你的选择的理由。如果没有哪一种容器优于其他容器,也请解释理由。 (a)读取固定数量的单词,将他们按字典顺序插入到...
  • sunhero2010
  • sunhero2010
  • 2016年03月31日 15:00
  • 2954

C++primer 顺序容器(3)

了解list系列容器的存储方式,理解他们的优劣势
  • ah_107
  • ah_107
  • 2016年10月04日 10:45
  • 1613

C++primer 顺序容器(2)

接上一篇,我们再来谈谈顺序容器的成员函数: c.insert(pos,elem);//即在pos位置插入元素elem 程序执行过程是将元素类型的对象拷贝到容器中去的。其中push系列的函数执行机理...
  • ah_107
  • ah_107
  • 2016年10月03日 21:04
  • 1572

C++ Primer 学习笔记14 顺序容器

6、访问元素     如果容器非空,那么容器类型的front和back成员将返回容器的第一个和最后一个元素的引用。 【与begin和end的对比:】     1)begin和end返回容器类型的...
  • shouhouxiaomuwu
  • shouhouxiaomuwu
  • 2014年12月09日 17:19
  • 426

顺序容器 - 1【C++ Primer 学习笔记 - 第九章】

顺序容器: vector :  支持快速随机访问 list      :  支持快速插入/ 删除 deque:  双端队列    double-ended queue 顺序容器适配器 s...
  • zhangwenan2010
  • zhangwenan2010
  • 2012年10月19日 11:42
  • 339

顺序容器 - 2【C++ Primer 学习笔记 - 第九章】

list ilist(10); // 空容器:*ilist.begin() 无法解引用 // 空容器:back()、front() 操作,未定义 if(!ilist.empty()) { list:...
  • zhangwenan2010
  • zhangwenan2010
  • 2012年10月22日 17:16
  • 314

【C++primer学习笔记】第9章 顺序容器

1、将一个容器复制给另一个容器的时候
  • moqihao
  • moqihao
  • 2014年09月22日 16:40
  • 177

C++ primer第二次阅读学习笔记(第9章: 顺序容器)

第九章 顺序容器 顺序容器内的元素按位置进行存储和访问。元素的排列次序与元素值无关,而是由元素添加到容器的次序决定的。 标准库定义了三种顺序容器类型:vector,list,deque。它们的差别...
  • ithzhang
  • ithzhang
  • 2012年05月20日 14:20
  • 2718

C++ Primer 学习笔记_29_STL实践与分析(3) --顺序容器的操作(下)

 STL实践与分析 --顺序容器的操作(下) 六、访问元素     如果容器非空,那么容器类型的front和back成员将返回容器的第一个和最后一个元素的引用。 【与begi...
  • u011744843
  • u011744843
  • 2015年06月29日 11:28
  • 320

c++primer学习笔记 ( 第九章 顺序容器)

9.1顺序容器的定义 #include #include #include vector ivec;   //定义一个空的vector类型, vector ivec2(ivec);  /...
  • xujinsmile
  • xujinsmile
  • 2012年03月23日 23:30
  • 1064
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【C++ Primer 学习笔记】: 容器和算法之【顺序容器】
举报原因:
原因补充:

(最多只允许输入30个字)