大三生活次日

  呼呼,這麼晚纔來更新。css

  今天上了不少課,感受也沒浪費到時間,但是就已經這麼晚了,多是沒有好好利用上課時間吧,明天開始要好好利用上課時間來作一些學習和計劃。今天雖然有不少計劃尚未完成。不過博客是必定要更的(必定要堅持下去!└(^o^)┘,並且好像寫出來的文章,排版樣子什麼的不太好,我決定明天早上修飾一下本身的博客,好比安裝客戶端,安裝插件,添加css什麼的,儘可能弄得美觀大方清楚一點。)算法

  好了,正式進入正題。編程

 

--------------------------華麗分割線--------------------------------數據結構

 

  今天學習了算法分析與設計,主要講了一些算法思想和知識,如今來總結一下。數據結構和算法

 

  編程的靈魂:函數

     數據結構+算法=程序。性能

     今天才正式注意到了這點,之前學了不少算法和數據結構,可是理論方面很凌亂,如今算是正確地認識到了何爲程序,何爲數據結構和算法的做用。簡單來講,算法就是解決問題的方法或者過程,若是把問題當作一個函數,算法能夠把輸入轉化爲輸出。而數據結構是數據的計算機表示和相應的一組操做。這兩大內容組合,就造成了咱們熟悉的程序。學習

 

  算法:優化

    由劉汝佳、黃亮著做的《算法藝術與信息學競賽》可知,基本算法可分爲四種,枚舉、貪心、遞歸與分治法、遞推。spa

    今天暫時不對此進行詳解,目測將於週五晚對此微博進行更新,詳細闡述這四種方法並舉些許例子來講明。

 

  時間複雜度和空間複雜度的計算:

    今天主要講的是這個。原本我對這方面的知識沒有學的很詳細,主要是之前使用的數據比較小,本身也沒有對程序算法優化頗有興趣,致使自身對算法的時間和空間複雜度理解不是很好。但這個方面的知識真的很重要,能夠用來評估你的算法寫的是否高效,合理,當初咱們的專業老師在上數據結構課時花了不少時間來說複雜度這門知識,惋惜我沒有認真聽,而不少算法書都把關於時間和空間複雜度的計算列入基本綱要,尤見其重要性。如今就來從新認識一下,也算是比較基礎的認識吧,之後會逐漸深究,爭取寫出更優化的程序。

  時間複雜度:

    同一問題可用不一樣算法解決,而一個算法的質量優劣將影響到算法乃至程序的效率。所以能夠這樣理解,計算機科學中,算法的時間複雜度做爲一個函數,可以定量描述該算法的運行時間。

    通常來講,可以準確地判斷兩個算法的性能好壞的方法就是各寫一個程序來觀察它們的運行狀況,可是這樣異常耗時而且程序並非算法的直接對應結果,可能會沒法避免一些和算法無關,只由程序代碼產生的問題。所以,咱們能夠運用時間複雜度,從理論上來估計和比較算法的運行效率。下面會詳細解釋時間複雜度的由來。

    在具體瞭解時間複雜度以前,須要瞭解一個概念--基本操做。抽象來講,基本操做,就是一個運行時間不依賴於操做數的操做。簡單來講,既然咱們是利用時間複雜度來估計算法的運行效率的,那咱們總得有個估量的依據吧,好比說哪些操做佔時最大,哪些操做佔時較小能夠忽略,咱們就把佔主要運行時間的操做看做爲基本操做,並做爲時間複雜度估計的依據。爲何說基本操做是不依賴於操做數的操做?有點混亂吧。這裏借鑑了《算法藝術與信息學競賽》的一個小例子來講明一下。好比兩個不大於100的正整數相加,那麼運行時間確定常數,基本操做就是加法操做,操做數就是那兩個幾乎不影響運行時間的不大於100的正整數,也就是加法操做並不依賴於操做數。可是,若是是兩個大小無限制(位數特別大)的兩個正整數相加呢?這時候,加法操做就不能當作是基本操做了,由於兩個極大數相加,咱們計算時是須要將兩個極大整數對應的位數相加,所以,這裏的加法操做就不能當作是基本操做了,由於操做數(即極大整數)對其操做的影響很大。那麼在這種狀況下,什麼纔是基本操做?可能你已經想到了,將對應位數相加的操做,就能夠當作是一個基本操做,由於每位位數是最大值爲9的操做數,其運行時間不依賴於它的操做數。學習基礎算法的時候可能不會發現這個概念的用處,但越往深研究越會發現,在不一樣時候,能夠把不一樣的操做當作基本操做,而基本操做的選擇就反映了你對問題的主要矛盾的認識。這個是很是重要的。

    如今理解一下時間頻度,參考百度百科,一個算法花費的時間與算法中語句(基本操做)的執行次數成正比例,所以,一個算法中的語句執行次數可稱爲語句頻度或時間頻度。記爲T(n)。

    如今咱們將輸入n稱爲問題的規模(可理解爲問題運行時間的大小),當n不斷變化時,時間頻度T(n)也會不斷變化。但有時咱們想知道它變化時呈現什麼規律。爲此,咱們引入時間複雜度概念。

     通常狀況下,算法中基本操做重複執行的次數是問題規模n的某個函數,用T(n)表示,如有某個輔助函數f(n),使得當n趨近於無窮大時,T(n)/f(n)的極限值爲不等於零的常數,則稱f(n)是T(n)的同數量級函數。記做T(n)=O(f(n)),稱O(f(n)) 爲算法的漸進時間複雜度,簡稱時間複雜度。

    時間頻度不一樣,但時間複雜度可能相同。如:T(n)=n2+3n+4與T(n)=4n2+2n+1它們的頻度不一樣,但時間複雜度相同,都爲O(n2)。有點繞,有點理論化是吧?回去看高數書應該又能夠理解了>_<|||。或者你能夠簡單得理解爲時間複雜度就是時間頻度的公式化,簡單化,好比n2+3n+4能夠簡化爲n2,由於在n無窮大時,他們趨近於相等。那爲何能夠這樣簡化呢?爲何稱之爲漸進時間複雜度呢?在這裏,咱們須要考慮一個問題,由於算法的運行時間可能和計算機的運行速度有關(好比某些操做運行快,某些操做運行慢),因此咱們只關心在問題規模擴大時時空開銷的增加狀況。是的,增加狀況,這是特別須要注意的。

    咱們再來看兩個例子:

    

1 int num = 1;;
2 for (i = 1; i <=n; i++) {
3   num *= i;
4 }
int num = 1;;
for (i = 1; i <= n; i++) {
  for (j = 1; j <= n; j++) {
    num =  num + i +j;  
   }
}

    這兩個例子中,變量i,j的自增並不影響算法的運行時間,因此咱們把加法和乘法操做當作是基本操做。那麼,第一份代碼執行了n個操做,第二份代碼執行了n2個操做。那麼哪一個運行速度更快呢?答案是不知道。是的,由於不知道加法操做和乘法操做哪一個快(聯繫前面所說,算法運行時間依賴於計算機的運行速度)。如今假設加法速度是乘法的10倍,那如今誰更快呢?還不必定,假設加法操做時間爲t,乘法操做時間爲10t,第一份代碼運行時間爲n*10t,第二份代碼運行時間爲n2*t,當n小於10時,第二份代碼運行較快,當n大於10時,第一代碼運行較快。

    可是,這樣依賴於n的規模大小(或者依賴於計算機運行速度)來估量算法運行時間,那答案就不惟一不肯定了,這樣的研究方法很不嚴謹。因此,在算法分析上來看,咱們觀察增加狀況來估量算法運行時間,會更優。好比,當n規模擴大10倍時,第一份代碼運行時間只擴大了10倍,可是第二份代碼運行時間會擴大100倍,就這樣觀察的話,第一份代碼運行速度更快更優,而且不依賴於計算機的運行。

    因此,進行算法分析的時候,咱們只對增加狀況作分析。到這裏就比較好理解爲何叫作漸進時間複雜度了吧?就是n趨向於無限大的時候,得出與時間頻度T(n)的增加狀況趨近的時間複雜度O(f(n)),用來更簡單直接得表示算法的運行時間。由於n越大,T(n)和時間複雜度越接近,因此就叫作漸進時間複雜度!(哎喲,解釋得好辛苦,不知道是否是越解釋越亂了=@~@=)

 

  ------------------- 停筆先 -----------

 

  好吧!眨眼之間發現寫了很久了,空間複雜度還沒寫呢 QAQ。但太晚了,週五再更吧。

  努力,晚安。

相關文章
相關標籤/搜索