跳转至

05 容器⚓︎

1109 个字 3 行代码 预计阅读时间 6 分钟

由于这门课应该默认学生已经上过 CS106B/X,所以对容器的具体用法就没有细讲,而我之前并没有上过这门课,所以一刷过后可能会补一下这里列出容器的常见用法。

容器(container:一种收集其他对象的对象,并能通过某些方式与之交互。容器有以下特点:

  • 组织性(organization:相类似的数据可以被打包在一起
  • 标准性(standardization:有着在预期范围内且能被实现的共同点
  • 抽象性(abstraction:用户能够较为容易地利用复杂的想法

一些典型的容器⚓︎

有以下常见容器:

vector⚓︎

  • std::vector<int> vec;:创建新的空向量
  • std::vector<int> vec(n);:创建一个包含 n 0 的向量
  • std::vector<int> vec(n, k);:创建一个包含 n k 的向量
  • vec.push_back(k);:将 k 加在向量的末端
  • vec.clear();:移除向量内所有元素
  • int k = vec[i];:得到索引为 i 的元素(不检查索引越界的情况)
  • vec.size();:查看向量大小(元素个数)
  • for (std::size_t i = 0; i < vec.size(); ++i) ...:遍历向量元素
  • vec[i] = k;:改变索引为 i 的元素的值(不检查索引越界的情况)

set⚓︎

  • std::set<int> s;:创建空集合
  • s.insert(k):将值 k 加入集合内
  • s.erase(k):从集合中移除值 k
  • if (s.count(k)) ...:检查值 k 是否在集合内
  • if (s.empty()) ...:检查集合是否为空

map⚓︎

  • std:::map<int, char> m;:创建空映射
  • m.insert({k, v}); /* or */ m[k] = v;:将键 k 和对应值 v 加入映射内
  • m.erase(k);:将键 k 从映射中移除
  • if (m.count(k)) ...:检查键 k 是否在映射内
  • if (m.empty()) ...:检查映射是否为空
  • char c = m.at(k); m.at(k) = v;:检索并覆写键 k 对应的值(若键不存在则报错
  • char c = m[k]; m[k] = v;:检索并覆写键 k 对应的值(若键不存在则自动插入

分类⚓︎

序列容器⚓︎

特点:

  • 按顺序访问容器
  • 内部有序的容器属于这类容器

例子

在高层次上,向量是规模可伸缩的一组相同类型元素的有序集,可看做数组。

它的一些成员变量(member variables

  • _size:向量的元素个数
  • _capacity:分配给元素的空间大小

暂时没有理解,待补充

部分序列容器对照表

容器 std::vector std::deque std::list
在前端插入 / 删除
在后端插入 / 删除 非常快 很快
索引访问 非常快 不可能
在中间插入 / 删除 很快
内存占用
结合(切片 / 合并) 很慢
稳定性 很差
  • 通常用std::vector可以应付大多数情况
  • 若需要再前端快速插入元素,考虑用std::deque
  • 若需要合并多个列表,考虑用std::list(不常用)

关联容器⚓︎

特点:

  • 容器不必有序
  • 更加容易搜索
  • 映射、集合等属于这类容器

例子

映射是由配对(pair)实现的:std::pair<const key, value>,其中键(key)是不可改变的常量。若知道配对的第一个属性(键,通过索引访问映射的方式(比如myMap[key])返回第二个属性(值

有序版本(默认)的映射和集合需要由比较符来定义,而无序映射和集合需要由一个自定义的散列函数来定义,因此无序映射和集合通常比它们的有序版本更快一些,当然也更复杂些,使用时根据情况自行权衡。

注:散列函数的知识回顾

容器适配器⚓︎

容器适配器(container adaptors)是容器的“包装纸”,它可以修改序列容器的接口,改成用户想要与容器的交互方式。

用容器适配器从 deque 中实现 queue

template <class T, class Container = deque<T>> class queue;

队列作为容器适配器被实现,使用一个来自被称为「底层容器(underlying container)的具体容器的,被封装好的对象,提供一组具体的成员函数来访问元素。元素可以被压入(push)具体容器的后端(back,又可以从前端(front)被弹出(pop

更具体些:

std::queue<int> stack_deque; // container = std::deque
std::queue<int, std::list<int>> stack_list // container = std::list

底层容器可能是某种标准容器类模板,或者别的设计好的容器类,它至少支持以下运算:

  • empty
  • size
  • front
  • back
  • push_back
  • pop_front

评论区

如果大家有什么问题或想法,欢迎在下方留言~