大部分人都知道,其實我們一般都不需要去學什麼演算法。除非是,要麼是學生(立志參加acm),或者做純粹演算法研究的專業人員,再者要麼是為了進一些大公司而準備面試,要麼是純興趣使然。真正因為參加工作要用很多演算法的人實在是少之又少。當然,或許做影象處理或者資料處理,資料探勘,再或者,有關搜尋引擎等等之類的東西(恕我才識淺陋,從這篇文章看各自相關演算法的應用領域:當今世界最為經典的十大演算法--投票進行時,亦可窺知一二)。我甚至認為,絕大部分的人是肯定掌握了一些跟資料結構有關的基本演算法的,所以,總而言之,我始終相信,乙個人,尤其是學生,實在是沒有必要花太多精力在演算法相關上的。
但有兩個朋友關於快速排序的理解,讓我對此前的觀點--認為不需要多學演算法,稍稍產生了懷疑。
自從我開始寫經典演算法研究系列之後,便有很多很多的朋友叫我寫一篇如何學習演算法的文章,或者談談演算法學習方面的心得與體會。本來之前是因為一來演算法這個東西在實際工作中應用不多(就像上面提到的快速排序演算法,標準庫里乙個sort直接搞定,根本不再需要你去寫十幾行的**,既如此,又何必重複造輪子)。二來是我個人覺得,學習這種事情你學就對了,只要你有興趣,便什麼問題都能解決。應該不用像一些「大家」,「專家」那樣扯起長篇大論。但現在,情況已經不同了(我特別討厭那些在我面前裝的人。說什麼自己演算法很牛逼,或者自以為是,或說乙個搞演算法研究的人可以去做圖書編輯,搞笑)。
關於如何學習演算法,下面,個人簡略談三點(學演算法= 興趣 + 態度 + 編碼 + 關注實踐應用):
興趣。學好任何乙個東西,首先便必須得具備興趣。演算法也不例外。如果你對演算法實在沒有興趣,也大可不必擔憂。畢竟,各有所愛。
態度,重試程度。如果你覺得因為演算法在實際工作中應用不多,或者標準庫里都封裝了一切。或者認為,最基本的快速排序都不必去了解,那麼此文可以一掃而過了。
實踐。看書,如資料結構方面的教材,一定要把各種最基本的資料結構,如陣列,字串,棧,堆,佇列,樹,圖弄得通通透透(其實,看我之前整理的微軟面試100題,也有很大幫助,因為那些面試題大多都跟資料結構和演算法相關的,而我也是這麼做過來的),其次便是如朋友天時通所說的,基本的迭代法,窮舉搜尋法,遞推法,遞迴法,貪婪法,分治法,動態規劃法,回溯法等等都要弄懂弄透。然後可以讀程式設計珠璣,演算法導論(很多人都說演算法導論看不懂,實則是其上面的很多數學證明,我也不是很懂。具體可多在紙上畫畫,如紅黑樹的相關操作及**),再加上推敲--反覆思考,反覆研究,最後編碼--關注和結合實際應用,編碼實現(寫**實現乙個演算法比研透乙個演算法更有用)。僅以上,無它也。
很多朋友還問到,我是怎麼學習演算法,或者說學習過程是怎樣的,我是這樣子學的:從去年12月開始接觸演算法起(寫第一篇演算法文章,a*搜尋演算法),我先是因為要寫有關演算法的文章,所以很多的時候都要去參考資料,包括書籍和網上的,特別注重把乙個演算法真正闡述清楚,而要闡述清楚的話,那麼我自己本身就得先把那個演算法真正弄懂弄透,即只有自己懂了,我才可以講明白。然後是我一直在做那有關微軟等公司的面試題(大部都涉及到資料結構和演算法),然後,再與他人多多交流,最後,在反覆推敲和思考某乙個演算法之後,我便開始編寫**實現某個演算法了。這就是我學演算法的學習過程。
個人認為,完整寫出這個快速排序還是不難的,不過要注意很多細節問題,如:
我們知道,快速排序的分治partition過程有兩種方法,一種是上面所述的兩個指標索引一前一後逐步向後掃瞄的方法(演算法導論上採用的是這種方法),還有一種方法是兩個指標從首位向中間掃瞄的方法(大多數的人和一般的教材採用的是這第二種首尾向中間掃瞄法)。
partition過程中,要注意一些邊界值問題。如i、j索引的初始化,for迴圈中,j從陣列中第乙個位置l 到倒數第二個位置h-1處,且是當data[j]<=privot(是小於等於,非小於),然後找到了之後,i++,再交換。最後還有一次data[i+1]與data[h]的交換。最後,便是返回值的問題,返回i+1。
第三個要注意的方面是遞迴處。if(l
主要要注意的問題就是上述三個方面。只要把握好細節,那麼快速排序演算法,二十幾行自能搞定。下圖是快速排序演算法的第二種實現(就是上面所提到的首尾向中間掃瞄法):
這裡,也要注意乙個小問題,就是上述partition過程中,while迴圈內,下述a,b兩個過程的順序不能搞錯。因為如果把a,b兩個過程調換過來的話,即相當於把data[l]先賦給了privot,所以那樣先從低處掃瞄的話,那麼data[i],即privot覆蓋了高處data[j] 的值。像原來的正常順序,為什麼又可以了列?因為data[l]已經儲存在privot裡面,所以 ,才不怕privot 覆蓋了低處的值。
while(data[j]>=privot && i你如果還不理解的話,看下如下的示例過程就知道了。首先,我們以正常的過程來進行第一趟排序:那如果上面的**a,b過程的順序被調換,也就是被弄錯了列?如下:a:38 7 1 2 5 6 4 //以第乙個元素為主元
2 8 7 1 5 6 4
b:2 7 1 8 5 6 4
c:2 1 7 8 5 6 4
d:2 1 7 8 5 6 4
e:2 137 8 5 6 4 //最後補上,關鍵字3
while(data[i]<=privot && i//以上三行為b過程排序的過程將如下所述,低處的元素8將覆蓋高處的元素4,元素4不像上面的元素3被事先儲存在privot裡,所以,元素4就丟了:while(data[j]>=privot && i//以上三行為a過程
a:38 7 1 2 5 6 4 //以第乙個元素為主元ok,有關快速排序演算法實現的更多版本,請參考此篇文章:十3 7 1 2 5 6 8
b:.....
二、快速排序演算法之所有版本的c/c++實現。
雖然實際專案中80%不需要自己構造演算法,但對足夠基礎的演算法有所了解是理所必然的。快速排序(僅指學生)寫不出來的確沒什麼,但與此同時,表露了乙個不重視基礎演算法的態度問題。
今天,我明白了一點,找工作一定要找與自己興趣相關的工作。否則,一切,無從談起。(本人**,18970930595,郵箱,[email protected])。以上任何言論,均代表本人觀點。
謝謝瀏覽,希望閒話之外,對你有所幫助。完。
由快速排序引申而來 如何學習演算法
大部分人都知道,其實我們一般都不需要去學什麼演算法。除非是,要麼是學生 立志參加acm 或者做純粹演算法研究的專業人員,再者要麼是為了進一些大公司而準備面試,要麼是純興趣使然。真正因為參加工作要用很多演算法的人實在是少之又少。當然,或許做影象處理或者資料處理,資料探勘,再或者,有關搜尋引擎等等之類的...
排序演算法學習 快速排序
快速排序 作為氣泡排序的一種改進 通過設定乙個標誌值 通常為陣列第乙個元素pivot 一次快排將陣列分成兩個部分,一部分 公升序 前一部分 小於標誌值pivot,另一部分大於標誌值 公升序 後面部分 各部分內部可以是 通常也是 無序的。通過遞迴地呼叫這樣的排序,使得最終陣列所有的元素有序。一次具體的...
排序演算法學習 快速排序
今天演算法實驗重新學習了快速排序演算法,對此有了一些理解,把它記錄在此以供日後學習。如下為快速排序演算法的被呼叫部分。int get loc int arr int low,int high arr low arr i arr i temp return i 返回基準位置 演算法本質是從後往前與從前...