C語言語言說到底只是工具,編寫程式碼本質上就是使用工具幹活,和建築工人使用建築工具幹活沒什麼兩樣。
讓程式設計具有魅力的是演算法。有人說,拿到問題,能夠設計出解決方案並且完成程式碼的是程式設計師,只會按照步驟編碼的是碼農。Git 之父 Linus(也是 Linux 之父)在談及 Git 時說,Git 本身使用的程式設計技巧不值一談,他真正感到驕傲的是 Git 的設計。
按照x度百科的解釋,演算法是指解題方案的準確而完整的描述,是一系列解決問題的清晰指令,演算法代表著用系統的方法描述解決問題的策略機制。
這樣的定義非常官方和書面化,按照我的理解,演算法其實就是解決問題的方法,是將一組輸入轉化成一組輸出的一系列計算步驟,只不過每一個計算步驟都要能在有限時間內完成。
每一個計算步驟都要能在有限時間內完成,至於為什麼,題主可以自己考慮一下哈。
例如已知長方形對角兩點座標,計算它的面積時,方法就是:計算長方形的長、寬,再利用公式 面積=長 x 寬。這就是演算法。演算法是解決一類問題的,只解決特定問題談演算法沒有意義。
比如,一個排序演算法應該能夠對任意一個數組排序,而不是隻能對某一個特定陣列排序。如果對陣列 int a[] = {1,3,4,2}; 排序,寫了這樣的一個C語言函式:
那顯然這不叫演算法,因為換一個數組這個方法就失效了,沒有通用性。真正的陣列排序演算法,應該能夠處理任意一組資料,並且都能輸出正確的結果。
如果對任意一個輸入,演算法都能在有限的時間內輸出正確的結果,則稱該演算法是正確的。所以演算法出錯有兩種可能,要麼是演算法會無限的計算下去,要麼就是演算法輸出了錯誤的結果。
不正確的演算法,只要其錯誤率可控,有時候可能是有用的。比如求一個方程的精確解可能開銷很大(比如要花費很長時間),但是求誤差允許範圍內的近似解卻很快就能完成,這也是可以接受的。
解決一個問題的方法(演算法)絕大多數情況下,都不止一種,合格的程式設計師應該儘量設計出開銷更小的演算法。接下來幾節,包括本節,我們將介紹幾種經典的陣列排序查詢演算法,一起來感受下不同演算法的差異。
對於少量元素的排序,插入排序法是一個有效的演算法。插入排序就像我們玩撲克牌一樣,拿到一張牌後,我們從右往左(或從左往右)將它與已在手中的每張牌做比較,以此決定它的插入位置。
就像圖中拿到一張梅花7,發現它比 10 小,繼續往左看,發現它比 5 大,所以把它插在 5 和 10 之間。為什麼不繼續比較左邊的 4 和 2 呢?這是因為之前的牌已經是排好序的。把 7 插入以後,一手牌又是排好序的了,下次接到牌可以繼續按照這個方法決定插入位置。
使用 C語言程式設計對陣列進行插入排序也是一樣的道理,只不過陣列的兩個元素之間不能插入,只能將插入點之後的元素往後移動一個單元。好了,現在思路清晰了,可以寫出演算法了,請看下面的C語言程式碼:
編譯並執行這段C語言程式碼,得到如下輸出:
容易看出,使用C語言解決這個排序問題時,我們並沒有使用多少“技巧”,就是簡單的賦值,if 判斷以及迴圈。
解決這個問題,最難的是設計算法,而不是編寫C語言程式碼,演算法弄通了,C語言程式碼很快就寫好了。
C語言語言說到底只是工具,編寫程式碼本質上就是使用工具幹活,和建築工人使用建築工具幹活沒什麼兩樣。
讓程式設計具有魅力的是演算法。有人說,拿到問題,能夠設計出解決方案並且完成程式碼的是程式設計師,只會按照步驟編碼的是碼農。Git 之父 Linus(也是 Linux 之父)在談及 Git 時說,Git 本身使用的程式設計技巧不值一談,他真正感到驕傲的是 Git 的設計。
那,什麼是演算法呢?按照x度百科的解釋,演算法是指解題方案的準確而完整的描述,是一系列解決問題的清晰指令,演算法代表著用系統的方法描述解決問題的策略機制。
這樣的定義非常官方和書面化,按照我的理解,演算法其實就是解決問題的方法,是將一組輸入轉化成一組輸出的一系列計算步驟,只不過每一個計算步驟都要能在有限時間內完成。
每一個計算步驟都要能在有限時間內完成,至於為什麼,題主可以自己考慮一下哈。
例如已知長方形對角兩點座標,計算它的面積時,方法就是:計算長方形的長、寬,再利用公式 面積=長 x 寬。這就是演算法。演算法是解決一類問題的,只解決特定問題談演算法沒有意義。
比如,一個排序演算法應該能夠對任意一個數組排序,而不是隻能對某一個特定陣列排序。如果對陣列 int a[] = {1,3,4,2}; 排序,寫了這樣的一個C語言函式:
那顯然這不叫演算法,因為換一個數組這個方法就失效了,沒有通用性。真正的陣列排序演算法,應該能夠處理任意一組資料,並且都能輸出正確的結果。
如果對任意一個輸入,演算法都能在有限的時間內輸出正確的結果,則稱該演算法是正確的。所以演算法出錯有兩種可能,要麼是演算法會無限的計算下去,要麼就是演算法輸出了錯誤的結果。
不正確的演算法,只要其錯誤率可控,有時候可能是有用的。比如求一個方程的精確解可能開銷很大(比如要花費很長時間),但是求誤差允許範圍內的近似解卻很快就能完成,這也是可以接受的。
解決一個問題的方法(演算法)絕大多數情況下,都不止一種,合格的程式設計師應該儘量設計出開銷更小的演算法。接下來幾節,包括本節,我們將介紹幾種經典的陣列排序查詢演算法,一起來感受下不同演算法的差異。
C語言陣列的插入排序法對於少量元素的排序,插入排序法是一個有效的演算法。插入排序就像我們玩撲克牌一樣,拿到一張牌後,我們從右往左(或從左往右)將它與已在手中的每張牌做比較,以此決定它的插入位置。
就像圖中拿到一張梅花7,發現它比 10 小,繼續往左看,發現它比 5 大,所以把它插在 5 和 10 之間。為什麼不繼續比較左邊的 4 和 2 呢?這是因為之前的牌已經是排好序的。把 7 插入以後,一手牌又是排好序的了,下次接到牌可以繼續按照這個方法決定插入位置。
使用 C語言程式設計對陣列進行插入排序也是一樣的道理,只不過陣列的兩個元素之間不能插入,只能將插入點之後的元素往後移動一個單元。好了,現在思路清晰了,可以寫出演算法了,請看下面的C語言程式碼:
編譯並執行這段C語言程式碼,得到如下輸出:
容易看出,使用C語言解決這個排序問題時,我們並沒有使用多少“技巧”,就是簡單的賦值,if 判斷以及迴圈。
解決這個問題,最難的是設計算法,而不是編寫C語言程式碼,演算法弄通了,C語言程式碼很快就寫好了。