第一章引论:
- 写出一个可以工作的程序远远不够,还要考虑在巨大的输入集上运行
- 一些数学知识复习
- 证明数据结构分析中最常见的两大方法:归纳法和反证法
- 递归简论(基准情况,不断推进,设计法则,合成效益法则)
练习1.1:书中给出了两种选择问题的解法,第一种很容易,这里给出第二种
int select(vector<int>& vec, int k) {
if (k > vec.size())
return -1;
else {
sort(vec.begin(), vec.end() - (vec.size()-k));
if (k == vec.size())
return vec[k - 1];
else {
for (int i = k; i != vec.size(); ++i) {
if (vec[i] < vec[i - 1])
swap(vec[i], vec[i - 1]);
}
}
}
return vec[k - 1];
}
选择问题还有一种很著名的解法BFPTR算法,时间复杂度为O(n),参考我的另一篇https://blog.csdn.net/lancelot0902/article/details/89003386
练习1.2:求解猜字谜游戏
思路:书中的两个方法都是对二维数组中的每个单词访问它的有序维度组(行,列,方向,字符数),检查每个是否合乎要求,这两种方法需要大量嵌套for循环,很麻烦,复杂度极高,这里就不列代码了
练习1.3:编写过程输出任意实数
因为是要求输出任意实数,所以参数采用double,但是浮点数在计算机中的存储有误差,所以要先减小误差,本程序中用的方法是round up(向上舍入)
double RoundUp(double N, int DecPlaces) {
double AmountToAdd = 0.5;
for (int i = 0; i < DecPlaces; ++i)
AmountToAdd /= 10;
return N + AmountToAdd;
}
void PrintDigit(int n) { //打印数字
cout << n;
}
void PrintFractionPart(double N, int DecPlaces) { //打印小数部分
double Fraction = FractionPart(N);
for (int i = 0; i < DecPlaces; ++i) {
Fraction *= 10;
PrintDigit(IntPart(Fraction));
Fraction = FractionPart(Fraction);
}
}
void Print(double N, int DecPlaces) { //打印所给数
if (N < 0) {
putchar('-');
N = -N;
}
N = RoundUp(N, DecPlaces);
PrintDigit(IntPart(N)); //输出整数部分
if (DecPlaces > 0)
putchar('.');
PrintFractionPart(N, DecPlaces);
}
int IntPart(double N) { //得到整数部分
return N;
}
double FractionPart(double N) { //得到小数部分
return N - static_cast<int>(N);
}
练习1.4:include语句包含文件的输出(递归)(C++实现)
ProcessFile函数的作用,读取文件时若遇到#include语句,则执行include语句后面包含的文件,一个文件中可以包含其它文件
void ProcessFile(const string& file_name) {
ifstream file(file_name);
string words;
while (getline(file, words)) {
istringstream is(words);
string word;
while (is >> word) {
if (word == "#include") {
string file_cp;
auto it = find(words.begin(), words.end(), '"');
for (++it; *it != '"'; ++it) {
file_cp.push_back(*it); //得到文件名
}
ProcessFile(file_cp);
}
cout << word << " ";
}
cout << endl;
}
}