这一章的题目叫做Programming: A General Overview。也就是对编程进行一个概述。这一章的内容挺丰富的,提到了本书的目的、数学基础知识、递归函数介绍以及C++的基础知识回顾,最后还提到了一个简单的矩阵的类。特别值得注意的是,这一章里回顾了C++ 11标准新引进的右值引用(rvalue reference)以及移动语义(move semantics)。没有系统学习过C++ 11的同学看起来可能觉得很困惑(当初我就是这样感觉的);不过不用着急,如果想要对C++ 11有一个比较好的理解的话,推荐大家看《Ivor Horton’s BeginningVisual C++ 2013》这本书,里面对C++ 11进行了比较详细的介绍。
下面开始对习题进行解答。
习题1.1
这道题让我们编程来解决本章一开始提出的选择问题(selection problem),并且还要画表格来表示对于不同的N所需的运行时间。为什么要画表格呢?直接在控制台里输出就OK了呀!当然为了计算时间,我#include了ctime库文件。计算时间还有很多其他方法,不过这个好像是在没有包含Windows API的情况下精确度最高、最便于使用的了。由于这一章里我们没有学习到任何高级算法,所以只能用本章一开始给出的两个思路了。这两种思路体现在了本题解答的两个函数里面,看官一阅便知。从运行结果上来看,至少对于我给出的这个实例,第二种思路确实要稍微快一些。
习题1.2
这道题让我们编程来解决本章一开始提出的单词谜题(word puzzle problem)。这里本人同样使用的是那里给出的两个思路。注意第二个函数假设了单次列表变量wordList是按升序排列的,并且需要一个辅助函数binarySearch进行二分法查找。虽然两个解法的思路都比较直接,但是编写的时候很容易出错,我就错了好几次。另外这个程序是用CMatrix(基本上就是本章最后给出的matrix类)的对象myBoard来储存字母的二维数组的。为了更加有意思,我让这个程序可以无限运行下去,用户每按一次键盘,myBoard就会随机化自己的内容,然后再调用两个函数来查找里面的单词,并给出相应的运行时间。从运行结果来看,第二种方法的效率要高一些;这个不难想见,因为一般来说wordList里的单词量会很多,比如说可以达到成千上万。
习题1.3
这道题让我们用正文中提到的只能够接收一个数字并将其输出的printDigit函数来输出一个任意的double类型的数。我在这道题的解答里提供了五个函数:除了printDigit和最终需要的printDouble外,还有printInt用于输出任意一个整数,以及两个分别返回一个double变量的整数部分和小数部分的辅助函数。
用户在输入的时候可能会发现一个奇怪的现象:输入的double数和经由printDouble输出的同一个数看起来有可能不一样。这个其实很正常,因为电脑是用二进制来存储double变量的,产生误差是在所难免的。此题也可以利用现成的将double转化为字符串的函数来获得更多便利,而且似乎这样做的话就没有上面的误差了;不过我没有试过,有兴趣的同学可以试试。
习题1.4
这道题让我们用被#include的文件的内容替换该#include语句。这道题其实是一种很初步的模拟C++编译器的练习。其实难度不大,主要在于分析文件的哪一行的第一个“单词”是“#include”,并在其后跟随合法的文件名时打开之并“复制”其内容于此处。当然,如果不注意的话,错误是难免的。
习题1.5
这道题让我们用递归方法来计算一个正整数的二进制表示中数字1的个数。这个很简单,直接用题中的提示就行了。不过为了验证结果的正确性,最好有一个输出正整数N的二进制表示的函数。本人上网找了一个完成此功能的函数,堪称是最简洁的版本了。值得注意的是,该程序在N为负数时将会失效。
习题1.6
这道题比较有难度,让我们用递归方法来实现字符串的全排列。这个网上很容易找到,这里就不细说了。值得注意的是,因为第二个permute的第一个参数是被const修饰的,所以在函数实现的内部要拷贝一个临时的对象以便进行元素的交换。所以,如果这个permute的第一个参数是string &的话,效率会提高很多的。
习题1.7
a.部分用数学归纳法很容易攻克;b.部分直接用定义验证就行了。
习题1.8
这四道小题难度依次加大。有兴趣的读者可以尝试一下,做不出来也没关系。
习题1.9
这道题让我们估计调和级数的前N项和的后半部分。其实本人也没有什么思路呀……
习题1.10
因为2^4模5同余于1,所以2^100=(2^4)^25模5同余于1^25=1。
习题1.11
前两道小题比较基本,用数学归纳法轻松搞定;第三题比较难,有兴趣的同学可以上网搜一下如何求出Fibonacci数列的通项公式。
习题1.12
这一题挺简单的,用数学归纳法攻克之。
习题1.13
这道题其实让我们简单地模拟一下STL库中的vector。STL中的vector除了保存它自己的尺寸(size)外,还要保存一个比之更大的成员变量——容量(capacity),以避免频繁的内存申请。不过这道题并没有说要定义容量,所以我们就无视之了。注意我这里对insert方法进行了重载,单变量的版本是在末尾插入,而带有另外一个insertInd参数的版本是在insertInd位置之前进行插入。
习题1.14
这道题可以说是上一题的升级版,因为这次的collection是有序的(虽然题目中并没有要求这样)。所以虽然大部分method一样,但是insert和remove的实现不一样了;我在它们内部嵌入了一个比较高级的二分查找算法。至于当collection为空时findMin和findMax将如何处理,我就简单地提示错误并强制退出程序了。
习题1.15
这道题没啥说的,其实就是让我们熟悉一下函数对象(function object)的用法。注意为了方便地看到程序的运行结果,我为CRectangle类重载了<<操作符。
习题1.16
这道题也很简单,没啥说的。为了能够看到运行结果,我重载了<<运算符。
--------------------------------------------------------------------------------------------------------------
下面就把这些习题解答的代码发上来吧!我进行了加密,所以只有看了本片博客才能知道如何解压,嘿嘿!
下载地址:
第一章代码
解压密码:
HarrySpiderman_Chap01