數據結構之算法

算法是解決特定問題求解步驟的描述,在計算機中表現爲指令的有限序列,而且每條指令表示一個或多個操做。算法

算法是須要單獨講解的,在數據結構中談到算法,是爲了幫助理解好數據結構,並不會詳談算法的方方面面。數據結構

兩種算法的比較

1+2+3+.....+100函數

算法1:測試

#include <stdio.h>

int main(void) {
    int i, sum = 0, n = 100;
	for(i = 1; i <= n; i++){
	    sum += i;
	}
	printf("%d", sum);
	return 0;
}

 算法2(高斯的算法):設計

#include <stdio.h>

int main(void) {
    int i, sum = 0, n = 100;
  sum = (1+n)*n/2;
  printf("%d", sum);
  return 0;
}

顯然高斯的算法厲害不少。blog

算法的特性

五個基本特性:輸入、輸出、有窮性、肯定性和可行性排序

一、輸入輸出數學

  算法具備林哥或多個輸入,但至少有一個或多個輸出,輸出的形式能夠是打印、返回一個或多個值。io

二、有窮性table

  算法在指定郵箱的步驟以後,自動結束而不會出現無限循環,且每一個步驟在可接受的時間內完成。

三、肯定性

  算法的每一步驟都具備肯定的含義,不會出現二義性。

四、可行性

  算法的每一步都必須是可行的。

算法設計的要求

 好的算法應該具備:正確性、可讀性、健壯性、高效率和低存儲量的特徵。

一、正確性

  至少應該具備輸入、輸出和加工處理無歧義性、能正確反映問題的要求,能獲得問題的正確答案。

  但一般對「正確」的理解有很大差異,大體分爲如下四個層次:

    (1)沒有語法錯誤;

    (2)合法的輸入數據能產生知足要求的輸出結果

    (3)非法的輸入數據能知足規格說明的結果;

    (4)精心選擇的,甚至刁難的測試數據都有知足要求的輸出結果

  證實一個複雜算在全部層次是正確的,代價很是昂貴,因此通常,咱們把層次3做爲一個算法是否正確的標準。

二、可讀性

  便於閱讀、理解和交流。可讀性是算法好壞很重要的標誌。

三、健壯性

  輸入數據不合法是,算法也能作出相關處理,而不是產生異常或莫名其妙的問題。

四、時間效率高和存儲量低

函數的逐漸增加

  判斷一個算法的效率時,函數中的參數和其餘次要項經常能夠忽略,而更應該關注主項(最高階項)的階數。

  某個算法,隨着n的增加,它會愈來愈優於另外一算法,或愈來愈差於另外一算法。

算法的時間複雜度

一、定義

  T(n)=O(f(n)) ,表示隨問題規模n的增大,算法執行時間的增加率和f(n)的增加率相同,稱爲算法的漸進時間複雜度,簡稱時間複雜度。其中f(n)是問題規模n的某個函數。

用O( )體現算法時間複雜度的記法,稱爲 大O記法。

二、推導大O階方法

  (1)用常數1取代運行時間中的全部加法常數。

  (2)在修改後的運行次數函數中,只保留最高階項。

  (3)若是最高階項存在且不是1,這去除與這個項相乘的常數。

  獲得的結果就是大O階。

舉例:

三、常數階

下面這個算法不是O(3),而是O(1)  

int i, sum = 0, n = 100; /*執行一次*/
sum = (1+n)*n/2; /*執行一次*/
printf("%d", sum); /*執行一次*/

執行時間恆定的算法,稱之爲具備O(1)的時間複雜度,又叫常數階

無論常數是多少,咱們都記做O(1),而不能是O(3)等其餘任何數字,這是初學者常犯的錯誤。

對於分支結構(不包含在循環結構中),不管真假,執行次數都是恆定的,因此其時間複雜度也是O(1).

四、線性階

  分析算法的複雜度,關鍵是要分析出循環結構的運行狀況。

  下面這段代碼是O(n),由於循環體要執行n次 

 int i, sum = 0, n = 100;
	for(i = 1; i <= n; i++){
	    sum += i;
	}

五、對數階

下面這段代碼,x = ㏒₂n,因此時間複雜度爲O(㏒n)

int count = 1, n = 100;
	while (count < n) {
	    count *= 2;
	}

六、平方階

下面這段代碼,循環體的嵌套,時間複雜度爲O(n²)

for(int i = 0;i <n; i++){
	    for(int j = 0;j <n; j++){
	        printf("test")
	    }
	}

理解大O推導不難,難的是對數列的一些相關運算,這更多的是考察你的數學知識和能力。

常見的時間複雜度

時間複雜度耗費時間從小到大排序依次是

執行次數函數 非正式術語
12 O(1) 常數階
5㏒₂n+20 O(㏒n) 對數階
2n+1 O(n) 線性階
2n+3n㏒₂n+19 O(n㏒n) n㏒n階
3n²+2n+1 O(n²) 平方階
6n³+2n²+3n+4

O(n³)

立方階
2ⁿ O(2ⁿ) 指數階

 

 

 

 

 

 

 

固然還有O(n!)和O(nⁿ),但O(n³)、O(2ⁿ)、O(n!)和O(nⁿ)除非很小的n值,不然哪怕n只是100,都是噩夢般的運行時間,對於這種不切實際的算法時間複雜度,通常都不討論它。

最壞狀況運行時間和平均運行時間

最壞狀況運行時間是一種保證,那就是運行時間將不會再壞了。在應用中,這是一種最重要的需求,一般,咱們提到的運行時間都是最壞狀況的運行時間。

而平均運行時間是全部狀況中最有意義的,由於它是指望的運行時間。

算法空間複雜度

寫代碼時,徹底能夠用空間換取時間。

算法的空間複雜度經過計算算法所需的存儲空間實現,算法空間複雜度的計算公式記做:S(n)=O(f(n))。

咱們討論的通常都是算法的時間複雜度。

相關文章
相關標籤/搜索