概括
對任何編程人員來說,一個永遠(yuǎn)繞不開的話題就是算法了,雖然有很多人表示,我不是算法工程師,不需要了解這東西。的確,很多時候我們的確用不到太多高深的算法,不過對于很多常用的算法,也許在我們不經(jīng)意間,就使用到了,只是我們還沒注意到而已,所以今天就簡單的聊一聊我們程序的算法中,最常用的幾種算法中的兩種,窮舉和遞歸
算法的定義
在維基百科中,對算法的定義是:在數(shù)學(xué)(算學(xué))和計算機科學(xué)之中,為任何良定義的具體計算步驟的一個序列,常用于計算、數(shù)據(jù)處理和自動推理。精確而言,算法是一個表示為有限長列表的有效方法。算法應(yīng)包含清晰定義的指令用于計算函數(shù)
算法的特性
如果說某某算法,那么它一定具備幾個特性或者標(biāo)準(zhǔn)
- 輸入:一個算法必須有零個或以上輸入量。
- 輸出:一個算法應(yīng)有一個或以上輸出量,輸出量是算法計算的結(jié)果。
- 明確性:算法的描述必須無歧義,以保證算法的實際執(zhí)行結(jié)果是精確地匹配要求或期望,通常要求實際運行結(jié)果是確定的。
- 有限性:依據(jù)圖靈的定義,一個算法是能夠被任何圖靈完全系統(tǒng)模擬的一串運算,而圖靈機只有有限個狀態(tài)、有限個輸入符號和有限個轉(zhuǎn)移函數(shù)(指令)。而一些定義更規(guī)定算法必須在有限個步驟內(nèi)完成任務(wù)。
- 有效性:又稱可行性。能夠?qū)崿F(xiàn),算法中描述的操作都是可以通過已經(jīng)實現(xiàn)的基本運算執(zhí)行有限次來實現(xiàn)。
時間復(fù)雜度和空間復(fù)雜度
上述描述了算法的標(biāo)準(zhǔn),不過,我們?nèi)粘V袑λ惴ǖ囊罂刹粌H如此,我們經(jīng)常說的時間復(fù)雜度和空間復(fù)雜度,就是我們對一個算法的常用標(biāo)準(zhǔn)了,對于這兩個概念我們也很好理解,一個是算法所需要的時間,一個是算法所需要的空間
對于一個功能,如果一個算法耗時是10毫秒,一個是100毫秒,我們可能會因為覺得10毫秒和100毫秒對于我們來說都是很短的時間,所以差別不大,但是當(dāng)計算機在某一時間連續(xù)運行這個算法幾十甚至上百次,那么我們就能明顯的感覺出這兩個算法的優(yōu)劣了
關(guān)于時間復(fù)雜度和空間復(fù)雜度,我們常用一個函數(shù)O(n)表示,n代表運行這個算法的次數(shù)
窮舉和遞歸
說了算法的一些基礎(chǔ)知識,接下來聊聊日常生活中常見的兩個算法(當(dāng)然,這里只說思想,不寫代碼)
窮舉法
窮舉法也叫蠻力法,相信很多人也用過這種算法,哪怕是不懂算法的人,也在某些功能中寫過這種算法。
窮舉法簡單的描述,就是在一個可能是問題解的集合內(nèi),拿這個集合所有的元素,一個個去嘗試,直到獲得問題的解或者遍歷完這個集合即可
這種算法常用的一個領(lǐng)域就是破解密碼方面了,對于一個我們未知的密碼,最簡單的破譯方式就是窮舉法,比如對于一個三位數(shù)的數(shù)字密碼,只需要嘗試999次就可以破譯出來,當(dāng)然,如果位數(shù)太大,或者字母符號的組合太大,那么破譯所需要的次數(shù)就大大加大了,這時就需要看我們計算機的計算速度了,如果計算機的速度夠快(比如國家使用的超級計算機),那么也能夠在短時間內(nèi)破譯一個密碼
遞歸法
說完了窮舉,再說說遞歸,簡單來說程序調(diào)用自身的方法就稱為遞歸,這個算法也是一個非常常見的算法。
例如遍歷文件夾,我們需要不斷的獲取文件夾中子文件夾的信息,然后對于這一個個子文件夾,我們又需要做同樣的操作,這樣就可以寫一個不斷調(diào)用自身的函數(shù),這種方式就是遞歸。當(dāng)然,對于遞歸,我們需要注意的是,因為這個算法會不斷的調(diào)用自己,所以如果一個函數(shù)調(diào)用的次數(shù)太多,那么就很容易出現(xiàn)內(nèi)存溢出,所以在我們使用這個算法時,需要判斷大致的調(diào)用次數(shù),以避免出現(xiàn)異常。
尾遞歸
剛才說了遞歸容易出現(xiàn)內(nèi)存異常,那么有沒有什么好的方式可以避免呢,答案是有的,這種方式叫做尾遞歸,如果一個函數(shù)中所有遞歸形式的調(diào)用都出現(xiàn)在函數(shù)的末尾,我們稱這個遞歸函數(shù)是尾遞歸的。很多編程語言,對于尾遞歸這種方式是有做優(yōu)化的,這種叫做尾遞歸優(yōu)化,這樣就避免了遞歸出現(xiàn)的內(nèi)存溢出,當(dāng)然并不是所有的編程語言有做這項優(yōu)化,所有當(dāng)我們使用遞歸的時候,需要事先了解我們使用的編程語言是否有尾遞歸優(yōu)化