數(shù)據(jù)結(jié)構(gòu)(二)——算法

算法

算法是解決特定問題求解步驟的描述,在計(jì)算機(jī)中表現(xiàn)為指令的有限序列焕数,并且每條指令表示一個(gè)或多個(gè)操作

1. 數(shù)據(jù)結(jié)構(gòu)與算法關(guān)系

數(shù)據(jù)結(jié)構(gòu):數(shù)據(jù)與數(shù)據(jù)之間的結(jié)構(gòu)關(guān)系(數(shù)組泽疆、隊(duì)列要门、樹榜晦、圖等結(jié)構(gòu))
算法:解決問題的步驟
數(shù)據(jù)結(jié)構(gòu)與算法關(guān)系:數(shù)據(jù)結(jié)構(gòu)是底層冠蒋,算法高層。數(shù)據(jù)結(jié)構(gòu)為算法提供服務(wù)乾胶。算法圍繞數(shù)據(jù)結(jié)構(gòu)操作抖剿。

2. 算法定義

什么是算法呢?算法是描述解決問題的方法识窿。算法(Algorithm)這個(gè)單詞最早出現(xiàn)在波斯數(shù)學(xué)家阿勒·花刺子密在公元825年(相當(dāng)于我們中國的唐朝時(shí)期)所寫的《印度數(shù)字算術(shù)》中斩郎。如今普遍認(rèn)可的對(duì)算法的定義是:算法是解決特定問題求解步驟的描述,在計(jì)算機(jī)中表現(xiàn)為指令的有限序列腕扶,并且每條指令表示一個(gè)或多個(gè)操作。

算法定義中吨掌,提到了指令半抱,指令能被人或機(jī)器等計(jì)算裝置執(zhí)行脓恕。它可以是計(jì)算機(jī)指令,也可以是我們平時(shí)的語言文字窿侈。
為了解決某個(gè)或某類問題炼幔,需要把指令表示成一定的操作序列,操作序列包括一組操作史简,每一個(gè)操作都完成特定的功能乃秀,這就是算法了。

3. 算法的特性

算法具有五個(gè)基本特性:輸入圆兵、輸出跺讯、有窮性、確定性和可行性殉农。

  1. 輸入輸出
    算法的輸入可以是零個(gè)刀脏,算法至少有一個(gè)或多個(gè)輸出。
  2. 有窮性
    算法在執(zhí)行有限的步驟之后超凳,自動(dòng)結(jié)束而不會(huì)出現(xiàn)無限循環(huán)愈污,并且每一個(gè)步驟在可接受的時(shí)間內(nèi)完成
  3. 確定性
    算法的每一步驟都具有確定的含義,不會(huì)出現(xiàn)二義性轮傍。算法在一定條件下暂雹,只有一條執(zhí)行路徑,相同的輸入只能有唯一的輸出結(jié)果创夜。算法的每個(gè)步驟被精確定義而無歧義杭跪。
  4. 可行性
    算法的每一步都必須是可行的,也就是說挥下,每一步都能夠通過執(zhí)行有限次數(shù)完成揍魂。可行性意味著算法可以轉(zhuǎn)換為程序上機(jī)運(yùn)行棚瘟,并得到正確的結(jié)果

4. 算法設(shè)計(jì)的要求

正確性 可讀性 健壯性 時(shí)間效率高和存儲(chǔ)量低

  1. 正確性
    算法的正確性是指算法至少應(yīng)該具有輸入现斋、輸出和加工處理無歧義性、能正確反映問題的需求偎蘸、能夠得到問題的正確答案庄蹋。
    但是算法的“正確”通常在用法上有很大的差別,大體分為以下四個(gè)層次迷雪。
    1 算法程序沒有語法錯(cuò)誤限书。
    2 算法程序?qū)τ诤戏ǖ妮斎霐?shù)據(jù)能夠產(chǎn)生滿足要求的輸出結(jié)果。
    3.算法程序?qū)τ诜欠ǖ妮斎霐?shù)據(jù)能夠得出滿足規(guī)格說明的結(jié)果章咧。
    4.算法程序?qū)τ诰倪x擇的倦西,甚至刁難的測(cè)試數(shù)據(jù)都有滿足要求的輸出結(jié)果。
    對(duì)于這四層含義赁严,層次1要求最低扰柠,但是僅僅沒有語法錯(cuò)誤實(shí)在談不上是好算法粉铐。這就如同僅僅解決溫飽,不能算是生活幸福一樣卤档。而層次4是最困難的蝙泼,我們幾乎不可能逐一驗(yàn)證所有的輸入都得到正確的結(jié)果。
    因此算法的正確性在大部分情況下都不可能用程序來證明劝枣,而是用數(shù)學(xué)方法證明的汤踏。證明一個(gè)復(fù)雜算法在所有層次上都是正確的,代價(jià)非常昂貴舔腾。所以一般情況下溪胶,我們把層次3作為一個(gè)算法是否正確的標(biāo)準(zhǔn)。

  2. 可讀性
    算法設(shè)計(jì)的另一目的是為了便于閱讀琢唾、理解和交流载荔。
    可讀性高有助于人們理解算法,晦澀難懂的算法往往隱含錯(cuò)誤采桃,不易被發(fā)現(xiàn)懒熙,并且難于調(diào)試和修改。

  3. 健壯性
    當(dāng)輸入數(shù)據(jù)不合法時(shí)普办,算法也能做出相關(guān)處理工扎,而不是產(chǎn)生異常或莫名其妙的結(jié)果衔蹲。
    一個(gè)好的算法還應(yīng)該能對(duì)輸入數(shù)據(jù)不合法的情況做合適的處理肢娘。比如輸入的時(shí)間或者距離不應(yīng)該是負(fù)數(shù)等。

  4. 時(shí)間效率高和存儲(chǔ)量低
    時(shí)間效率指的是算法的執(zhí)行時(shí)間舆驶,對(duì)于同一個(gè)問題橱健,如果有多個(gè)算法能夠解決,執(zhí)行時(shí)間短的算法效率高沙廉,執(zhí)行時(shí)間長(zhǎng)的效率低拘荡。
    存儲(chǔ)量需求指的是算法在執(zhí)行過程中需要的最大存儲(chǔ)空間,主要指算法程序運(yùn)行時(shí)所占用的內(nèi)存或外部硬盤存儲(chǔ)空間撬陵。設(shè)計(jì)算法應(yīng)該盡量滿足時(shí)間效率高和存儲(chǔ)量低的需求
    比如在生活中珊皿,人們都希望花最少的錢,用最短的時(shí)間巨税,辦最大的事蟋定,算法也是一樣的思想,最好用最少的存儲(chǔ)空間草添,花最少的時(shí)間驶兜,辦成同樣的事就是好的算法。

5.算法效率的度量方法

事后統(tǒng)計(jì)方法 事前分析估算方法

  1. 事后統(tǒng)計(jì)方法
    通過設(shè)計(jì)好的測(cè)試程序和數(shù)據(jù),利用計(jì)算機(jī)計(jì)時(shí)器對(duì)不同算法編制的程序的運(yùn)行時(shí)間進(jìn)行比較抄淑,從而確定算法效率的高低犀盟。
    **缺陷: **

    • 必須依據(jù)算法事先編制好程序,這通常需要花費(fèi)大量的時(shí)間和精力蝇狼。
    • 時(shí)間的比較依賴計(jì)算機(jī)硬件和軟件等環(huán)境因素,有時(shí)會(huì)掩蓋算法本身的優(yōu)劣倡怎。
    • 算法的測(cè)試數(shù)據(jù)設(shè)計(jì)困難迅耘,并且程序的運(yùn)行時(shí)間往往還與測(cè)試數(shù)據(jù)的規(guī)模有很大關(guān)系,效率高的算法在小的測(cè)試數(shù)據(jù)面前往往得不到體現(xiàn)监署。
  2. 事前分析估算方法
    在計(jì)算機(jī)程序編制前颤专,依據(jù)統(tǒng)計(jì)方法對(duì)算法進(jìn)行估算。
    一個(gè)用高級(jí)程序語言編寫的程序在計(jì)算機(jī)上運(yùn)行時(shí)所消耗的時(shí)間取決于下列因素:

    1. 算法采用的策略钠乏、方法栖秕。
    2. 編譯產(chǎn)生的代碼質(zhì)量。
    3. 問題的輸入規(guī)模晓避。
    4. 機(jī)器執(zhí)行指令的速度簇捍。

    第1條當(dāng)然是算法好壞的根本,第2條要由軟件來支持俏拱,第4條要看硬件性能暑塑。拋開這些與計(jì)算機(jī)硬件、軟件有關(guān)的因素锅必,一個(gè)程序的運(yùn)行時(shí)間事格,依賴于算法的好壞問題的輸入規(guī)模。所謂問題輸入規(guī)模是指輸入量的多少搞隐。

在分析一個(gè)算法的運(yùn)行時(shí)間時(shí)驹愚,重要的是把基本操作的數(shù)量與輸入規(guī)模關(guān)聯(lián)起來,即基本操作的數(shù)量必須表示成輸入規(guī)模的函數(shù)


隨著n值的越來越大劣纲,它們?cè)跁r(shí)間效率上的差異也就越來越大逢捺。

6. 算法時(shí)間復(fù)雜度

算法時(shí)間復(fù)雜度定義

在進(jìn)行算法分析時(shí),語句總的執(zhí)行次數(shù)T(n)是關(guān)于問題規(guī)模n的函數(shù)味廊,進(jìn)而分析T(n)隨n的變化情況并確定T(n)的數(shù)量級(jí)蒸甜。算法的時(shí)間復(fù)雜度,也就是算法的時(shí)間量度余佛,記作:T(n)=O(f(n))柠新。它表示隨問題規(guī)模n的增大,算法執(zhí)行時(shí)間的增長(zhǎng)率和f(n)的增長(zhǎng)率相同辉巡,稱作算法的漸近時(shí)間復(fù)雜度恨憎,簡(jiǎn)稱為時(shí)間復(fù)雜度。其中f(n)是問題規(guī)模n的某個(gè)函數(shù)。
這樣用大寫O( )來體現(xiàn)算法時(shí)間復(fù)雜度的記法憔恳,我們稱之為大O記法瓤荔。
一般情況下,隨著n的增大钥组,T(n)增長(zhǎng)最慢的算法為最優(yōu)算法输硝。

O(1)叫常數(shù)階、O(n)叫線性階程梦、O(n 2)叫平方階

  1. 叫常數(shù)階
//實(shí)例1
int sum = 0,n = 100;      /* 執(zhí)行一次 */
sum = (1 + n) * n / 2;    /* 執(zhí)行一次 */
printf("%d", sum);        /* 執(zhí)行一次 */
//實(shí)例2
int sum = 0, n = 100;     /* 執(zhí)行1次 */
sum = (1 + n) * n / 2;    /* 執(zhí)行第1次 */
sum = (1 + n) * n / 2;    /* 執(zhí)行第2次 */
sum = (1 + n) * n / 2;    /* 執(zhí)行第3次 */
sum = (1 + n) * n / 2;    /* 執(zhí)行第4次 */
sum = (1 + n) * n / 2;    /* 執(zhí)行第5次 */
printf("%d", sum);        /* 執(zhí)行1次 */

無論n為多少点把,執(zhí)行時(shí)間恒定的算法,我們稱之為具有O(1)的時(shí)間復(fù)雜度屿附,又叫常數(shù)階郎逃。
注意:不管這個(gè)常數(shù)是多少,我們都記作O(1)挺份,而不能是O(3)褒翰、O(12)等其他任何數(shù)字,這是初學(xué)者常常犯的錯(cuò)誤匀泊。
對(duì)于分支結(jié)構(gòu)而言优训,無論是真,還是假各聘,執(zhí)行的次數(shù)都是恒定的型宙,不會(huì)隨著n的變大而發(fā)生變化,所以單純的分支結(jié)構(gòu)(不包含在循環(huán)結(jié)構(gòu)中)伦吠,其時(shí)間復(fù)雜度也是O(1)妆兑。

  1. 線性階O(n)
    線性階的循環(huán)結(jié)構(gòu)會(huì)復(fù)雜很多。要確定某個(gè)算法的階次毛仪,我們常常需要確定某個(gè)特定語句或某個(gè)語句集運(yùn)行的次數(shù)秉沼。
    分析算法的復(fù)雜度带膀,關(guān)鍵就是要分析循環(huán)結(jié)構(gòu)的運(yùn)行情況滑频。
int i;
for (i = 0; i < n; i++){  
     /* 時(shí)間復(fù)雜度為O(1)的程序步驟序列 */
}
//它的循環(huán)的時(shí)間復(fù)雜度為O(n)著拭,因?yàn)檠h(huán)體中的代碼須要執(zhí)行n次。
  1. 對(duì)數(shù)階O(logn)
int count = 1;
while (count < n){   
     count = count * 2;
    /* 時(shí)間復(fù)雜度為O(1)的程序步驟序列 */
}

由于每次count乘以2之后衡怀,就距離n更近了一分棍矛。也就是說,有多少個(gè)2相乘后大于n抛杨,則會(huì)退出循環(huán)够委。由2 x=n得到x=log 2 n。所以這個(gè)循環(huán)的時(shí)間復(fù)雜度為O(logn)怖现。

4.平方階O(m×n)

int i, j;
for (i = 0; i < n; i++){
     for (j = 0; j < n; j++)    { 
       /* 時(shí)間復(fù)雜度為O(1)的程序步驟序列 */   
    }
}

內(nèi)循環(huán)剛才我們已經(jīng)分析過茁帽,時(shí)間復(fù)雜度為O(n)玉罐。而對(duì)于外層的循環(huán),不過是內(nèi)部這個(gè)時(shí)間復(fù)雜度為O(n)的語句潘拨,再循環(huán)n次吊输。所以這段代碼的時(shí)間復(fù)雜度為O(n 2 )。

所以可以總結(jié)得出铁追,循環(huán)的時(shí)間復(fù)雜度等于循環(huán)體的復(fù)雜度乘以該循環(huán)運(yùn)行的次數(shù)季蚂。

推導(dǎo)大O階方法

推導(dǎo)大O階:
1.用常數(shù)1取代運(yùn)行時(shí)間中的所有加法常數(shù)。
2.在修改后的運(yùn)行次數(shù)函數(shù)中琅束,只保留最高階項(xiàng)癣蟋。
3.如果最高階項(xiàng)存在且不是1,則去除與這個(gè)項(xiàng)相乘的常數(shù)狰闪。
得到的結(jié)果就是大O階。

7.常見的時(shí)間復(fù)雜度

執(zhí)行次數(shù) 函數(shù)階 非正式術(shù)語

  • O(1) 常數(shù)階2n+3
  • O(n) 線性階3n 2 +2n+1
  • O(n 2 ) 平方階5log 2 n+20
  • O(logn) 對(duì)數(shù)階2n+3nlog 2 n+19
  • O(nlogn) nlogn階6n 3 +2n 2 +3n+4
  • O(n 3 ) 立方階2 n
  • O(2 n ) 指數(shù)階

常用的時(shí)間復(fù)雜度所耗費(fèi)的時(shí)間從小到大依次是:

O(1) < O(logn) < O(n) < O(nlogn) < O(n 2 ) < O(n 3 ) < O(2 n ) < O(n!)<O(n n )

8. 總結(jié)回顧

算法的定義:算法是解決特定問題求解步驟的描述濒生,在計(jì)算機(jī)中為指令的有限序列埋泵,并且每條指令表示一個(gè)或多個(gè)操作。
算法的特性:有窮性罪治、確定性丽声、可行性、輸入觉义、輸出雁社。
算法的設(shè)計(jì)的要求:正確性、可讀性晒骇、健壯性霉撵、高效率和低存儲(chǔ)量需求。
算法的度量方法:事后統(tǒng)計(jì)方法(不科學(xué)洪囤、不準(zhǔn)確)徒坡、事前分析估算方法。
函數(shù)的漸近增長(zhǎng):給定兩個(gè)函數(shù)f(n)和g(n)瘤缩,如果存在一個(gè)整數(shù)N喇完,使得對(duì)于所有的n>N,f(n)總是比g(n)大剥啤,那么锦溪,我們說f(n)的增長(zhǎng)漸近快于g(n)。于是我們可以得出一個(gè)結(jié)論府怯,判斷一個(gè)算法好不好刻诊,我們只通過少量的數(shù)據(jù)是不能做出準(zhǔn)確判斷的,如果我們可以對(duì)比算法的關(guān)鍵執(zhí)行次數(shù)函數(shù)的漸近增長(zhǎng)性牺丙,基本就可以分析出:某個(gè)算法坏逢,隨著n的變大,它會(huì)越來越優(yōu)于另一算法,或者越來越差于另一算法是整。
推導(dǎo)大O階:用常數(shù)1取代運(yùn)行時(shí)間中的所有加法常數(shù)肖揣。在修改后的運(yùn)行次數(shù)函數(shù)中,只保留最高階項(xiàng)浮入。如果最高階項(xiàng)存在且不是1龙优,則去除與這個(gè)項(xiàng)相乘的常數(shù)。
常見的時(shí)間復(fù)雜度所耗時(shí)間的大小排列:O(1)<O(logn)<O(n)<O(nlogn)<O(n 2 )<O(n 3 )<O(2 n )<O(n!)<O(n n )

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末事秀,一起剝皮案震驚了整個(gè)濱河市彤断,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌易迹,老刑警劉巖宰衙,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異睹欲,居然都是意外死亡供炼,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門窘疮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來袋哼,“玉大人,你說我怎么就攤上這事闸衫√喂幔” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵蔚出,是天一觀的道長(zhǎng)弟翘。 經(jīng)常有香客問我,道長(zhǎng)骄酗,這世上最難降的妖魔是什么衅胀? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮酥筝,結(jié)果婚禮上滚躯,老公的妹妹穿的比我還像新娘。我一直安慰自己嘿歌,他們只是感情好掸掏,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著宙帝,像睡著了一般丧凤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上步脓,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天愿待,我揣著相機(jī)與錄音浩螺,去河邊找鬼。 笑死仍侥,一個(gè)胖子當(dāng)著我的面吹牛要出,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播农渊,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼患蹂,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了砸紊?” 一聲冷哼從身側(cè)響起传于,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎醉顽,沒想到半個(gè)月后沼溜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡游添,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年系草,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片否淤。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖棠隐,靈堂內(nèi)的尸體忽然破棺而出石抡,到底是詐尸還是另有隱情,我是刑警寧澤助泽,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布啰扛,位于F島的核電站,受9級(jí)特大地震影響嗡贺,放射性物質(zhì)發(fā)生泄漏隐解。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一诫睬、第九天 我趴在偏房一處隱蔽的房頂上張望煞茫。 院中可真熱鬧,春花似錦摄凡、人聲如沸续徽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽钦扭。三九已至,卻和暖如春床绪,著一層夾襖步出監(jiān)牢的瞬間客情,已是汗流浹背其弊。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留膀斋,地道東北人梭伐。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像概页,于是被迫代替她去往敵國和親籽御。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355