爛代碼和好代碼

好的代碼應該是簡單直接、邏輯清晰的,bug 難以隱藏的。即時沒有註釋讀一遍也能看懂。 而爛代碼邏輯混亂,寫完過段時間本身都看不懂。ios

這裏從一些問題出發對比好代碼爛代碼,但願你們共同提升。數組

1 紅黑磚迷陣問題

問題描述[1]函數

有一個矩形的房間裏鋪滿正方形瓷磚。每塊瓷磚塗成黑色或紅色。一我的站在黑色的瓷磚上,今後出發,能夠移動到四個相鄰的瓷磚之一,但只能移動到黑色的瓷磚上。計算他經過重複上述移動所能通過的黑磚數。spa

這裏把紅色改爲了白色,其餘不變。思路原做者描述的很詳細了。.net

/* 樣例輸入輸出
6 9  //列數、行數
BBBBWB
BBBBBW
BBBBBB
BBBBBB
BBBBBB
BBBBBB
BBBBBB
W@BBBW
BWBBWB
45

0 0 //結束標誌
*/

這裏對比一下個人實現(爛代碼)和原做者的實現(好代碼)code

#include<iostream>
#include<cstdio>
#include<string>
#include<vector>
using namespace std;
int g=0;
vector<vector<bool> > isvisit;
/*1. 因爲每次輸入的是字符串,考慮用vector<string>表示該二維矩陣,cin>>str輸入每行。
用char a[][];cin>>a[i] 更方便*/
void reach(vector<string>&v,int x,int y,int h,int w)
{

    if(isvisit[x][y] || v[x][y]=='W') return;

    g++;
    isvisit[x][y]=true;

    //cout<<x<<" "<<y<<" "<<g<<" "<<v[x][y]<<endl;
		/*2. 探索函數,順序爲左右上下
		把全部邊界條件寫到函數入口更好更方便。*/
    //left
    if(y>0 ) reach(v,x,y-1,h,w);
    //right
    if(y<w-1 ) reach(v,x,y+1,h,w);
    //up
    if(x<h-1) reach(v,x+1,y,h,w);
    //down
    if(x>0 ) reach(v,x-1,y,h,w);
}
int main()
{
    int w,h;//width height//列數、行數
    while(cin>>w>>h)
    {
        if(w==0 && h==0) break;
        vector<string> v(h,"");//1. 初始化矩陣v
        // true: visited
				//初始化二維vector
        isvisit=vector<vector<bool> >(h,vector<bool>(w,false));
        int sx=0;
        int sy=0;
        bool isfindat=false;
        for(int i=0;i<h;i++)
        {
            cin>>v[i];
            if(isfindat==false)
            {
                for(int j=0;j<v[i].size();j++)
                {
                    if(v[i][j]=='@')
                    {
                        sx=i;
                        sy=j;
                        isfindat=true;
                    }
                }
            }
        }

        g=0;
        reach(v,sx,sy,h,w);
        cout<<g<<endl;
    }
}
*/

原做者blog

#include <iostream>
#include<cstring>
using namespace std;
// R 紅磚 B 黑磚 @人
const int MAX_ROW = 20, MAX_COLUMN = 20;
int sum, m, n;    //通過的瓷磚數    行數    列數
char map[MAX_ROW][MAX_COLUMN];
bool visited[MAX_ROW][MAX_COLUMN]; //記錄訪問標誌的數組

//遞歸計算從(row,col)出發通過的瓷磚數
void search(int row, int col)
{
    //邊界條件 座標在地圖外,不可通行,已經訪問過 則回溯
		// 擦做者這裏col>=n寫錯了,坑死了,找了2個小時
    if (row < 0 || row >= n || col < 0 || col >= m || map[row][col] == 'W' || visited[row][col])
    return;

		//cout<<row<<" "<<col<<" "<<sum<<endl;
    visited[row][col] = true; //設置當前座標的標誌位
    ++sum; //通過的瓷磚數+1
    //遞歸遍歷當前座標的四個相鄰點
    search(row , col-1);
    search(row, col+1);
    search(row-1, col);
    search(row+1 , col);
}

int main(){
    while (cin >> m >> n) //輸入列數和行數
    {
        if(m==0 && n==0) break;
        int row, col;
        for (int i = 0; i < n; i++)
        {
            cin>> map[i]; //輸入當前行的數據集
            for (int j = 0; j < m; j++)
            {
                if (map[i][j] == '@')
                {
                    row = i;
                    col = j;
                }
            }
        }
        //cout<<row<<" "<<col<<endl;
        memset(visited,false,sizeof(visited));
        sum = 0;
        search(row, col);
        cout << sum << endl;
    }
    return 0;
}

2 調整數組順序使奇數位於偶數前面

題目描述[2]排序

輸入一個整數數組,實現一個函數來調整該數組中數字的順序,使得全部的奇數位於數組的前半部分,全部的偶數位於位於數組的後半部分,並保證奇數和奇數,偶數和偶數之間的相對位置不變。遞歸

v1 將原數組分割成兩個子數組,而後再合併,時間複雜度O(n),空間複雜度較高。ci

void reOrderArray(vector<int> &array) {
        vector<int> odd;//odd numbers
        vector<int> eve;//even numbers
        for(int i=0;i<array.size();i++)
        {
            if(array[i]%2==0)
                odd.push_back(array[i]);
            else
                eve.push_back(array[i]);
        }
        array.clear();
        array.insert(array.begin(),eve.begin(),eve.end());
        array.insert(array.end(),odd.begin(),odd.end());
    }

v2 將數組分爲前半段(奇數)和後半段(混合)。用相似插入排序的思路把每次找到的奇數插入到前半段。等前半段增加結束就排好了。

&1判斷奇數更高效

時間複雜度O(n^2),空間複雜度O(1)

void reOrderArray(vector<int> &v) {
        if(v.empty())   return;
        int lastodd=0;
        for(int i=0;i<v.size();i++)
        {
            if(v[i] & 1)
            {
                int t=v[i];
                for(int j=i-1;j>=lastodd;j--)
                {
                    v[j+1]=v[j];
                }
                v[lastodd]=t;
                lastodd++;
            }
        }
    }

References

  1. 遞歸回溯法實戰(一)——(Red and Black)紅黑磚迷陣(POJ1979)
  2. http://www.nowcoder.com/practice/beb5aa231adc45b2a5dcc5b62c93f593