設計C語言算法時,怎樣才算合格?感覺算法好難,基於數組的歸併排序算法該如何理解?

3 個回答
嵌入式时代
2019-06-23

謝邀。

我的上個回答簡要討論了下什麼是算法,並且介紹了C語言程序開發中比較基本的數組排序算法——插入排序法,如果題主看了,應該有助於理解本題。設計C語言算法時,怎樣才算合格?感覺算法好難,基於數組的歸併排序算法該如何理解?

事實上,讓C語言編程具有魅力的是算法,拿到問題,能夠設計出解決方案並且完成代碼的是程序員,只會按照步驟編碼的是碼農。

這是上個回答的主題,有朋友看到也有感而發:在評論區說,“程序是骨架,算法才是靈魂”。的確,C語言程序只是指令,計算機只會冷冰冰的按照指令辦事,它並不能解決問題,真正解決問題的還是人


什麼樣的算法才是好的算法呢?

假設計算機是無限快的,並且存儲器是免費的無限大的,那最好的算法就是最容易實現的算法。

然而,計算機也許是快的,但它們不是無限快。存儲器也許是廉價的,但不是免費的。所以計算時間是一種有限資源,存儲器的空間也一樣。優秀的程序員應該盡力設計出開銷更小的算法設計C語言算法時,怎樣才算合格?感覺算法好難,基於數組的歸併排序算法該如何理解?

下面再討論下C語言程序開發中,數組的歸併排序算法,這種算法也是比較經典的排序法,在數組元素非常多的情況下,效率遠遠高於插入排序法。

什麼是歸併排序呢?

歸併排序的定義,希望瞭解“一本正經”的官方書面定義可以自行百科。這裡就不寫了,因為“冷冰冰的”書面定義對不瞭解它的人來說太難懂。

我打算用一些容易理解的例子來解釋它。

假設有一個C語言數組需要排序,那數組長度為多長最簡單呢?顯然是長度為 1 時,排序最簡單,什麼都不需要做,就能夠排好序。設計C語言算法時,怎樣才算合格?感覺算法好難,基於數組的歸併排序算法該如何理解?

歸併排序的基本思路就是這樣:把長數組一直拆分下去,直到最後不能拆分為止,這時長數組被拆分為若干個長度為 1 的數組,長度為 1 的數組顯然是排好序的了。

例如下圖是一個長度為 5 的數組,為了排序,先把它拆分到不能繼續拆為止。

設計C語言算法時,怎樣才算合格?感覺算法好難,基於數組的歸併排序算法該如何理解?

接著,只要把這些排好序的子數組按照從小到大的順序合併,就可以得到最終排好序的數組了。

設計C語言算法時,怎樣才算合格?感覺算法好難,基於數組的歸併排序算法該如何理解?

好了,現在知道歸併排序的算法了,那怎樣使用 C語言編程完成這個算法呢?

使用C語言編程實現歸併排序算法

歸併排序算法總體可以分為兩步:拆分數組,合併數組。先來看看怎樣使用C語言實現數組的拆分。

使用C語言拆分數組

對數組拆分有多種方法,這裡選擇平分法。設計C語言算法時,怎樣才算合格?感覺算法好難,基於數組的歸併排序算法該如何理解?

如果使用 start 表示數組頭,end 表示數組尾,每次平均拆分,都會將數組分為 start 到 mid,和 mid+1 到 end 兩部分,其中 mid 表示中間點,所以 mid = (start+end)/2。就這樣一直拆分下去,直到不能繼續拆分為止

不能拆分時,start 應該不再小於 end。

拆分數組的數學描述完畢了,容易看出,遞歸(如果題主對C語言的遞歸不理解,可以查看我之前的問答或者文章。)非常適合解決這樣的問題。我們現在用C語言來實現這樣的拆分,先確定遞歸的基礎條件:

設計C語言算法時,怎樣才算合格?感覺算法好難,基於數組的歸併排序算法該如何理解?

拆分過程會在 start 不再小於 end 時停下。其他情況時,拆分會繼續下去,相關C語言代碼如下,請看:

設計C語言算法時,怎樣才算合格?感覺算法好難,基於數組的歸併排序算法該如何理解?

divide(start, mid); 負責拆分前半段,divide(mid+1, end); 負責拆分後半段。這樣的 divide 函數可以把數組拆分到不可拆分為止。

使用C語言合併數組

使用 divide 函數把數組拆分完畢後,就可以按照從小到大的順序把各個元素合併到原來的數組了。

設計C語言算法時,怎樣才算合格?感覺算法好難,基於數組的歸併排序算法該如何理解?

由於兩個子序列都已經排好序了,所以 merge() 函數的C語言代碼很簡單,每次循環取兩個子序列中最小的元素進行比較,將較小的元素取出放到最終的排序序列中,如果其中一個子序列的元素已取完,就把另一個子序列剩下的元素都放到最終的排序序列中。

使用C語言實現數組的歸併排序

數組的拆分和合並函數都寫好了,可以把它倆結合起來,實現數組的排序了。

設計C語言算法時,怎樣才算合格?感覺算法好難,基於數組的歸併排序算法該如何理解?

測試C語言實現的歸併排序

這裡使用 8 個元素的數組做測試:

設計C語言算法時,怎樣才算合格?感覺算法好難,基於數組的歸併排序算法該如何理解?

編譯並執行這段C語言代碼,發現數組被成功排序了。

設計C語言算法時,怎樣才算合格?感覺算法好難,基於數組的歸併排序算法該如何理解?

到這裡,相信題主應該明白如何使用C語言實現數組的歸併排序了。它和插入排序算法都屬於排序算法,但是二者的效率差異性卻很大。

程序員一般如何衡量算法的效率呢?數組的插入排序法和歸併排序法的效率差異性到底有多大呢?我之前的文章已經比較詳細的討論過,題主可以點擊我的主頁查看。

設計C語言算法時,怎樣才算合格?感覺算法好難,基於數組的歸併排序算法該如何理解?

歡迎在評論區一起討論,質疑。文章都是手打原創,每天最淺顯的介紹C語言、linux等嵌入式開發,喜歡我的文章就關注一波吧,可以看到最新更新和之前的文章哦。

编程之路坚持不懈
2019-06-23

學習算法是有基礎要求的,尤其是一些複雜的算法,比如:離散數學,數理邏輯,數據結構等,所以學習算法肯定會覺得難。算法的好壞評估標準通俗的講就是效率高低,不僅包括時間效率,還包括空間效率。算法學習建議先學習一些簡單的,再逐步深入。

天变道常
2019-06-23

不要搞這些複雜算法,先學會冒泡,再學微積分,概率,線性代數和矩陣,最後再搞高級的算法

相關推薦

推薦中...