好的代碼應該是簡單直接、邏輯清晰的,bug 難以隱藏的。即時沒有註釋讀一遍也能看懂。 而爛代碼邏輯混亂,寫完過段時間本身都看不懂。ios
這裏從一些問題出發對比好代碼爛代碼,但願你們共同提升。數組
問題描述[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]排序
輸入一個整數數組,實現一個函數來調整該數組中數字的順序,使得全部的奇數位於數組的前半部分,全部的偶數位於位於數組的後半部分,並保證奇數和奇數,偶數和偶數之間的相對位置不變。遞歸
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++; } } }