觀《編程之美》,談讀後之感

    近來觀《編程之美》,收穫頗多,總體上仍是值得稱道的,對讀者思惟的拓展和看問題的角度助益甚多,確能體會到編程之「美」,餘觀「一摞烙餅的排序」,感受甚「爽」。但讀此書過程當中,發現此書略有瑕疵,雖瑕不掩瑜,仍是決定在此予以指出(固然也多是我弄錯了呀):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;
}
View Code

(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;
}
View Code

(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;
}
View Code

(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;
}
View Code

 

另外,還有一篇關於」求二進制數種1的個數「的文章,用二分法作的,做者獨闢蹊徑,看法獨到,有興趣的讀者能夠前往:http://blog.csdn.net/justpub/article/details/2292823排序

相關文章
相關標籤/搜索