所謂的演算法,有時候幾十行程式碼就能搞定!
點選上方“中興開發者社群”,關注我們
每天讀一篇一線開發者原創好文
很多人認為,演算法是數學的內容,學起來特別麻煩。我們不能認為這種觀點是錯誤的。但是我們也知道,軟體是一種複合的技術,如果一個人只知道演算法,但是不能用程式語言很好地實現,那麼再優秀的演算法也不能發揮作用。
有一次,一個人問我:“你寫的都是小兒科的東西,幾十行程式碼就能搞定,能不能整一點高深的演算法?”
我反問他什麼是他所理解的高深的演算法,他答覆說:“像遺傳演算法、蟻群演算法之類的。”於是我給了他一個遺傳演算法求解0-1揹包問題的例子,並告訴他,這也就是幾十行程式碼的演算法,怎麼理解成是高深的演算法?他剛開始不承認這是遺傳演算法,直到我給了他Denis Cormier公開在北卡羅來納州立大學伺服器上的遺傳演算法的原始碼後,他才相信他一直認為深不可測的遺傳演算法的原理原來是這麼簡單。
還有一個人直言“用三個水桶等分8升水”之類的問題根本就稱不上演算法,他認為像“阿法狗”那樣的人工智慧才算是演算法。我告訴他計算機下棋的基本理論就是博弈樹,或者再加一個專家系統。但是他認為博弈樹也是很高深的演算法,於是我給了他一個井字棋遊戲,並告訴他,這就是博弈樹搜尋演算法,非常智慧,你絕對戰勝不了它(因為井字棋遊戲很簡單,這個演算法會把所有的狀態都搜尋完)。我相信他一定很震驚,因為這個演算法也不超過100行程式碼。
對於上面提到的例子,我覺得主要原因在於大家對演算法的理解有差異,很多人對演算法的理解太片面,很多人覺得只有名字裡包含“XX演算法”之類的東西才是演算法。而我認為演算法的本質是解決問題,只要是能解決問題的程式碼就是演算法。
一個人只有有了很好的計算機知識和數學知識,才能在演算法的學習上不斷進步。不管演算法都麼簡單,都要自己親手實踐,只有不斷認識錯誤、不斷髮現錯誤,才能不斷提高自己的程式設計能力,不斷提高自己的業務水平。
其實任何演算法都有自己的應用環境和應用場景,沒有演算法可以適用於所有的場景。這一點希望大家明白。同時,我們也要清楚複雜的演算法都是由普通的演算法構成的,沒有普通的演算法就沒有複雜的演算法可言,所以複雜變簡單,由大化小,這就是演算法分治遞迴的基本思想。
我們可以下面一個陣列查詢的函式說起。一句一句講起,首先我們開始從最簡單的函式構造開始:
1. int find(int array[], int length, int value)
2. {
3. int index = 0;
4. return index;
5. }
這裡看到,查詢函式只是一個普通的函式,那麼首先需要判斷的就是引數的合法性:
1. static void test1()
2. {
3. int array[10] = {0};
4. assert(FALSE == find(NULL, 10, 10));
5. assert(FALSE == find(array, 0, 10));
6. }
這裡可以看到,我們沒有判斷引數的合法性,那麼原來的查詢函式應該怎麼修改呢?
1. int find(int array[], int length, int value)
2. {
3. if(NULL == array || 0 == length)
4. return FALSE;
5.
6. int index = 0;
7. return index;
8. }
看到上面的程式碼,說明我們的已經對入口引數進行判斷了。那麼下面就要開始寫程式碼了。
1. int find(int array[], int length, int value)
2. {
3. if(NULL == array || 0 == length)
4. return FALSE;
5.
6. int index = 0;
7. for(; index < length; index++){
8. if(value == array[index])
9. return index;
10. }
11.
12. return FALSE;
13. }
上面的程式碼已經接近完整了,那麼測試用例又該怎麼編寫呢?
1. static void test2()
2. {
3. int array[10] = {1, 2};
4. assert(0 == find(array, 10, 1));
5. assert(FALSE == find(array, 10, 10));
6. }
執行完所有的測試用例後,我們看看對原來的程式碼有沒有什麼可以優化的地方。其實,我們可以把陣列轉變成指標。
1. int find(int array[], int length, int value)
2. {
3. if(NULL == array || 0 == length)
4. return FALSE;
5.
6. int* start = array;
7. int* end = array + length;
8. while(start < end){
9. if(value == *start)
10. return ((int)start - (int)array)/(sizeof(int));
11. start ++;
12. }
13.
14. return FALSE;
15. }
如果上面的程式碼引數必須是通用的資料型別呢?
1. template<typename type>
2. int find(type array[], int length, type value)
3. {
4. if(NULL == array || 0 == length)
5. return FALSE;
6.
7. type* start = array;
8. type* end = array + length;
9. while(start < end){
10. if(value == *start)
11. return ((int)start - (int)array)/(sizeof(type));
12. start ++;
13. }
14.
15. return FALSE;
16. }
此時,測試用例是不是也需要重新修改呢?
1. static void test1()
2. {
3. int array[10] = {0};
4. assert(FALSE == find<int>(NULL, 10, 10));
5. assert(FALSE == find<int>(array, 0, 10));
6. }
7.
8. static void test2()
9. {
10. int array[10] = {1, 2};
11. assert(0 == find<int>(array, 10, 1));
12. assert(FALSE == find<int>(array, 10, 10));
13. }
(1)我們的演算法需要測試用例的驗證
(2)任何的優化都要建立在測試的基礎之上
(3)測試和程式碼的編寫要同步進行
(4)演算法的成功執行時一步一步進行得,每一步的成功必須確立在原有的成功之上
相關文章
- 所謂併發程式設計,所謂有其三程式設計
- 不要浪費時間去寫所謂的完美程式碼
- 十行Python程式碼搞定圖片中的物體檢測Python
- 所謂BAPIAPI
- 聊聊所謂的cookieCookie
- 這就是所謂的結對程式設計?程式設計
- 同事有話說 | 那些所謂的敏捷儀式感敏捷
- 所謂的職場祕籍
- 金融大資料分析還不簡單,有了Smartbi簡單幾步就能搞定大資料
- 幾十行程式碼實現一個vue的狀態管理行程Vue
- 趣圖:有時候我寫的程式碼,就是這樣子的
- linux中查詢IP地址時出現所謂的“亂碼”問題Linux
- php->所謂"hook"PHPHook
- 所謂軟體工程軟體工程
- 幾行程式碼搞定java生成解析二維碼功能行程Java
- 何謂“好的程式碼”? (轉)
- 寫程式的時候,音樂是有講究的
- 談所謂價值投資
- 通用 PopupWindow,幾行程式碼搞定 PopupWindow 彈窗(續)行程
- Laravel 日誌有時候有許可權有時候沒有許可權?Laravel
- 不用程式碼,2小時搞定自己的網站網站
- 用幾十行程式碼實現python中英文分詞行程Python分詞
- 聊聊所謂的彈性工作制
- 所謂的執行緒安全問題執行緒
- 30 行 Python 程式碼搞定 X 演算法Python演算法
- 這就是所謂的OC的反射機制反射
- 幾十行程式碼實現ASP.NET Core自動依賴注入行程ASP.NET依賴注入
- 幾行程式碼就能實現為何要多此一舉行程
- pypy有時候執行python程式錯誤Python
- 程式設計師日常丨接親的時候寫程式碼,沒個幾年的功力,寫得出來嗎?程式設計師
- 十幾行程式碼搞定Android呼叫支付寶支付行程Android
- 為什麼寫程式碼的時候聽音樂?
- 為什麼寫程式碼的時候聽音樂
- 所謂Serverless,你理解對了嗎?Server
- 所謂網際網路產品
- 十行程式碼實現牛頓方法行程
- 二十行C#程式碼打造Ruby Markup BuilderC#UI
- 你打算敲程式碼到什麼時候?