跳至内容
Topos Uranos

摘要

这节课开启本课程的第六单元,主题是复合数据。它说明本单元的用途:教会表示数据的集合(固定大小和可变大小的序列、表格和记录),并用基本算法处理它们,这些算法既有亲手写的,也有取自库的,同时估计其代价;介绍本单元的六节课以及把它们串起来的线索;回顾本单元假定已有的知识,尤其是带不变式的循环和按常量引用传递;提出本单元要解决的问题,即一个程序必须保存数量未知的数据,而若用一个个单独的变量来写,它会把多出来的数据默默略过;预先介绍代价,作为衡量算法的第二个尺度,与正确性并列;并说明本单元通向何处,包括后面各单元以及“C++ 程序设计 II”课程。

学习目标

  1. 描述本单元的内容顺序,并说明每节课为后一节课提供了什么。
  2. 回顾循环、循环的不变式和参数的传递(按值、按引用和按常量引用),必要时加以复习。
  3. 借助一个例子,预先理解算法的代价,把它作为衡量算法质量的第二个尺度,与正确性并列。
  4. 认清学完本单元时应当会做什么,并把它与后面各单元将要学习的内容区分开来。

入门测评

在学习本单元之前,先测一测自己的起点是有益的。这项测评是自我测评:不计分,唯一的目的是为学习指引方向。前四道题检查本单元假定已经掌握的内容:求最大值的循环的不变式、大参数的传递方式、两层嵌套循环的轮数,以及无符号算术。其后的六道题按课的顺序涉及本单元的核心思想:序列的有效下标、向量的创建、一个大小能被对半分多少次、在有序数据中查找、表格的双重下标,以及把同一实体的数据存放在彼此分离的集合中的危险。没有人必须现在就答对,其中有几道题里,“我还不知道”是诚实的回答:每个答案,无论对错,都会解释要点,并指出讲解这一要点的那节课。同样的能力会在单元末尾的总结课中再次测量。

入门测评

开始本单元之前,先测一测你的起点。这是一次简短的自我测评:不计分,结果只保存在你的浏览器中。

  1. 第 1 题来自前面的单元代码片段 int largest{0}; int t{}; while (std::cin >> t) { if (t > largest) { largest = t; } } 应当在 largest 中留下读到的温度中最大的一个。它在什么输入下会出错?

  2. 第 2 题来自前面的单元一个函数计算一段存放在 std::string 中、长达一百万个字符的文本里有多少个元音,并且不修改它。它的形参最好怎样声明?

  3. 第 3 题来自前面的单元++count 在 for (int i{0}; i < 6; ++i) { for (int j{0}; j < i; ++j) { ++count; } } 中执行多少次?

  4. 第 4 题来自前面的单元std::println("{}", 0u - 1); 在 unsigned int 为 32 位的系统上输出什么?

  5. 第 5 题在一个有 nn 个元素、像 C++ 那样编号的序列中,哪些下标 ii 指示一个元素?

  6. 第 6 题执行 v 的定义 std::vector<int> v(3, 7); 之后,它包含什么?

  7. 第 7 题for (int m{1024}; m > 1; m /= 2) { ... } 转多少轮?

  8. 第 8 题一本电话簿按字母顺序列有一百万个名字。要找其中一个,就从中间翻开,舍弃名字不可能在其中的那一半,再对另一半重复这一做法。最多需要翻开多少次?

  9. 第 9 题对于 std::vector<std::vector<int>> t{{1, 2, 3}, {4, 5, 6}};,t[1][0] 和 t.size() 各是多少?

  10. 第 10 题一个程序把一组人的名字存放在一个向量里,把他们的成绩存放在另一个向量里,使得成绩 grades[i] 就是 names[i] 的成绩。如果只对成绩向量排序,会发生什么?