近來觀《編程之美》,收穫頗多,總體上仍是值得稱道的,對讀者思惟的拓展和看問題的角度助益甚多,確能體會到編程之「美」,餘觀「一摞烙餅的排序」,感受甚「爽」。但讀此書過程當中,發現此書略有瑕疵,雖瑕不掩瑜,仍是決定在此予以指出(固然也多是我弄錯了呀):ios
一、本書風格不統一,建議代碼所有改成僞碼。編程
二、表述不夠流暢,願多加潤色。less
三、結構之法這章太簡單。ide
四、發現書中的一些錯誤(打字錯誤就不在此指出了)和能夠優化的地方,現貼在此:優化
(1)、在」NIM(3)兩堆石頭的遊戲「中,代碼有邏輯錯誤,下面是改正以後的代碼(錯誤在註釋中予以說明了):spa
#include <iostream> #include <vector> #include <cmath> using namespace std; bool nim(int x, int y) { if(x == y) return true; if (x > y) { swap(x, y); } if (x == 1 && y == 2) { return false; } vector<int> iv; iv.push_back(2); int delta = 1; int n = 1; int b = 2; int addition = 0; while (x > n) { while (find(iv.begin(), iv.end(), ++n) != iv.end()); ++delta; ++addition; b = n + delta; iv.push_back(b); if (iv.size() > 2 && addition >= 100) { iv.erase(remove_if(iv.begin(), iv.end(), bind2nd(less<int>(), n)), iv.end()); addition = 0; } } if ((x != n) || y != b) { //y != b 爲改正以後的代碼 return true; } return false; } void tester1(int x, int y) { if (nim(x, y)) { cout<<"("<<x<<", "<<y<<") Can Win"<<endl; }else{ cout<<"("<<x<<", "<<y<<") Will lose"<<endl; } } bool nim2(int x, int y) { if (x == y) { return true; } if (x > y) { swap(x, y); } double a = (1 + sqrt(5.0)) / 2; return x != (int)floor((y - x) * a); } void tester2(int x, int y) { if (nim2(x, y)) { cout<<"("<<x<<", "<<y<<") Can Win"<<endl; }else{ cout<<"("<<x<<", "<<y<<") Will lose"<<endl; } } int main(int argc, const char * argv[]) { cout<<"The Tester1:"<<endl; tester1(1, 2); tester1(3, 5); tester1(3, 6); tester1(8, 10); tester1(8, 13); tester1(50, 50); tester1(5000, 5555); cout<<"The Tester2:"<<endl; tester2(1, 2); tester2(3, 5); tester2(3, 6); tester2(8, 10); tester2(8, 13); tester2(50, 50); tester2(5000, 5555); return 0; }
(2)、在」螞蟻爬杆「中,代碼有邏輯錯誤,下面是改正以後的代碼(錯誤在註釋中予以說明了):.net
#include <iostream> using namespace std; void CalcTime(double length, double* xpos, int antNum, double speed, double& min, double& max) { double totalTime = length / speed; max = 0; min = 0; double currentMin, currentMax; for (int i = 0; i < antNum; ++i) { currentMax = 0; currentMin = 0; if (xpos[i] > (length / 2)) { currentMax = xpos[i] / speed; }else{ currentMax = (length - xpos[i]) / speed; } //這裏爲改正以後的代碼,原書爲:currentMin = totalTime - Max; currentMin = totalTime - currentMax; if (currentMax > max) { max = currentMax; } if (currentMin > min) { //這裏爲改正以後的代碼,原書爲:min < currentMin min = currentMin; } } } int main(int argc, const char * argv[]) { // insert code here... double xpos[] = {3, 7, 11, 17, 23}; double min, max; CalcTime(27, xpos, 5, 1, min, max); cout<<min<<endl; cout<<max<<endl; return 0; }
(3)、在」計算字符串的類似度「中,加入了不須要的判斷(優化在註釋中予以說明了):code
#include <iostream> using namespace std; int inline Min(int lhs, int rhs) { return lhs < rhs ? lhs : rhs; } int CalculateStringDistance(char *strA, int pABegin, int pAEnd, char *strB, int pBBegin, int pBEnd) { if (pABegin > pAEnd) { if (pBBegin > pBEnd) { return 0; }else{ return pBEnd - pBBegin + 1; } } if (pBBegin > pBEnd) { //如下注釋部分爲原書的代碼,這裏根本就不須要判斷,與前面的判斷重合了 // if (pABegin > pAEnd) { // return 0; // }else{ // return pAEnd - pABegin + 1; // } return pAEnd - pABegin + 1; } if (strA[pABegin] == strB[pBBegin]) { return CalculateStringDistance(strA, pABegin + 1, pAEnd, strB, pBBegin + 1, pBEnd); }else{ int t1 = CalculateStringDistance(strA, pABegin, pAEnd, strB, pBBegin + 1, pBEnd); int t2 = CalculateStringDistance(strA, pABegin + 1, pAEnd, strB, pBBegin, pBEnd); int t3 = CalculateStringDistance(strA, pABegin + 1, pAEnd, strB, pBBegin + 1, pBEnd); return Min(t1, Min(t2, t3)) + 1; } } #define ARRLEN(arr) sizeof(arr)/sizeof(int) int main(int argc, const char * argv[]) { // insert code here... char strA[] = "aaabcdef"; char strB[] = "abcdefgdd"; size_t lenA = strlen(strA); size_t lenB = strlen(strB); int len = CalculateStringDistance(strA, 0, lenA - 1, strB, 0, lenB - 1); cout<<len<<endl; return 0; }
(4)、在」數字啞謎和迴文「中,number顯然能夠從10開始判斷,在循環判斷中加入break,能夠下降接近五分之一的代碼執行次數,讀者能夠自行實驗:blog
#include <iostream> #include <string.h> int main(int argc, const char * argv[]) { // insert code here... bool flag; bool IsUsed[10]; int number, revert_number, t, v; for (number = 10; number < 100000; ++number) { flag = true; memset(IsUsed, 0, sizeof(IsUsed)); t = number; revert_number = 0; for (int i = 0; i < 5; ++i) { v = t % 10; revert_number = revert_number * 10 + v; t /= 10; if (IsUsed[v]) { flag = false; break; //在此處加了break,原書沒有,能夠減小接近五分之一的執行次數 }else{ IsUsed[v] = 1; } } if (flag && (revert_number % number == 0)) { v = revert_number / number; if (v < 10 && !IsUsed[v]) { printf("%d * %d = %d\n", number, v, revert_number); } } } return 0; }
另外,還有一篇關於」求二進制數種1的個數「的文章,用二分法作的,做者獨闢蹊徑,看法獨到,有興趣的讀者能夠前往:http://blog.csdn.net/justpub/article/details/2292823排序