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

本系列博客主要是在学习 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 队列和优先级队列

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值