資料結構與演算法 二 時間複雜度和空間複雜度

2021-10-03 08:50:30 字數 3595 閱讀 1804

演算法採用的策略、方案

編譯產生的**質量

問題的輸入規模

機器執行指令的速度

由此可見,拋開計算機硬體,乙個程式的執行時間依賴於演算法的好壞和輸入規模。

int i,sum=

0,n=

100;

for(i=

1;i<=n;i++

)printf

("%d"

,sum)

;

int i,sum=

0,n=

100;

sum=

(i+n)

*n/2

;printf

("%d"

,sum)

;

例如上一講中提到了1-100之間求和,兩種演算法其實就是n和1的差距。

我們研究演算法的複雜度,側重的是研究演算法隨著輸入規模擴大增長量的乙個抽象,而不是精確的定位需要執行多少次。

我們不關心語言、環境等,只關心它所實現的演算法。

我們在分析乙個演算法的執行時間時,重要的是把基本操作的數量和輸入模式關聯起來

做乙個測試:兩個演算法的輸入規模都是n,a需要執行2n+3次,b需要執行3n+1次,那哪乙個更快些呢?

從這張表可以看出,n=1時,a演算法不如b演算法,隨著n的增長,a演算法開始反超,總體來講演算法a比b更優秀

演算法時間複雜度的定義:

(1)時間頻度:乙個演算法執行所耗費的時間,從理論上是不能算出來的,必須上機執行測試才能知道。但我們不可能也沒有必要對每個演算法都上機測試,只需知道哪個演算法花費的時間多,哪個演算法花費的時間少就可以了。並且乙個演算法花費的時間與演算法中語句的執行次數成正比例,哪個演算法中語句執行次數多,它花費時間就多。乙個演算法中的語句執行次數稱為語句頻度或時間頻度。記為t(n)。

(2)時間複雜度:在剛才提到的時間頻度中,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)) 為演算法的漸進時間複雜度,簡稱時間複雜度。

一般情況下,隨著輸入規模n的增大,t(n)增長最慢的演算法為最優演算法

顯然,利用時間複雜度,可以算出我們的兩個求和演算法的時間複雜度分別為o(1),o(n)。

推導方法:

常數階:

這裡舉乙個例子

int sum=

0,n=

100;

printf

("hello world!");

printf

("hello world!");

printf

("hello world!");

printf

("hello world!");

printf

("hello world!");

printf

("hello world!");

printf

("hello world!");

printf

("hello world!");

sum =(1

+n)*n/

2;

這裡的時間複雜度並不是o(8),而是o(1),因為printf的次數並不隨著時間規模的增大而增大。

線性階一般含有非巢狀迴圈涉及線性階,隨著n的增大,對應計算次數呈直線增長。例如

int i,sum=

0,n=

100;

for(i=

1;i<=n;i++

)

時間複雜度為o(n)。

平方階對於巢狀的迴圈,例如:

int i,j,n=

100;

for(i=

1;i<=n;i++

)}

時間複雜度為o(n)。

對數階我們看下這個程式:

int i=

1,n=

100;

while(i}

每次迴圈,i*2,離n更近一步,假設有x個2相乘後大於等於n,就會退出迴圈

於是由2^x=n得到x=log2n,所以這個程式的時間複雜的為o(logn)。

n++

;function

(n);

for(i=

0;i)for

(i=0

;i)}

上述**的時間複雜度為o(n^2);

常見的時間複雜度例子

時間複雜度

型別5201314

o(1)

常數階3n+4

o(n)

線性階3n^2+4n+5

o(n^2)

平方階3log2n+4

o(logn)

對數階2n+3nlog2n+14

o(nlogn)

nlogn階

n^3 +2n^2+4n+6

o(n^3)

立方階2^n

o(2^n)

指數階常用的時間複雜度所耗費的時間從小到大依次是:

o(1)3)n)所以說,演算法分析中,我們查詢乙個有n個隨機數陣列中的某個數字,最好的情況是第乙個數字就是,那麼時間複雜度就是o(1),但也有可能在這最後乙個位置,就是o(n)。

平均執行時間是期望的執行時間

最壞執行時間是一種保證。在應用中,這是一種最重要的需求,通常除非特別指定,我們提到的執行時間都是指最壞情況的執行時間

首先我們要明白,我們在寫**時,完全可以用空間來換取時間。

舉個例子,判斷某一年是否為閏年,我們可以實現要給演算法,每給乙個年份,都會通過演算法計算得到是否是閏年的結果。

另一種演算法就是,建立乙個陣列,將所有年份按下標的數字對應,如果是閏年,則此陣列元素對應的值為1,否則為0.

對比兩個演算法,第一種演算法很明顯節約空間,但是每一次查詢都需要進行運算,而第二種演算法,雖然在記憶體中存了幾千個陣列,但是每次查詢只需要一次索引即可。

這就是典型的空間換時間

演算法的空間複雜度通過計算演算法所需的儲存空間實現,演算法的空間複雜度的計算公式為:

s(n)=o(f(n)),其中,n為問題的規模,f(n)為語句關於n所儲存空間的函式。

通常,我們都是用"時間複雜度"來指執行時間的需求,是用"空間複雜的"值空間需求。

當直接要求我們求「複雜度」時,通常是指時間複雜度

顯然,對時間複雜度的追求更屬於演算法的潮流。

資料結構與演算法(二) 時間複雜度和空間複雜度

演算法採用的策略,方案 編譯產生的 質量 問題的輸入規模 機器執行指令的速度 由此可見,拋開這些與計算機硬體 軟體有關的因素,乙個程式的執行時間依賴於演算法的好壞和問題的輸入規模 我們研究演算法的複雜度,側重的是研究演算法隨著輸入規模擴大增長量的乙個抽象,而不是精確的定位需要執行多少次 我們不關心語...

資料結構和演算法(二) 時間複雜度和空間複雜度

演算法效率的度量方法 事後統計方法 這種方法主要是通過設計好的測試程式和資料,利用計算機計時器對不同酸防編制的程式執行時間進行比較,從而確定演算法效率的高低。這種方法有很大的缺陷,必須依據演算法事先編制好測試程式,通常需要花費大量時間和精力,如果完了發覺測試的是糟糕的演算法,就會功虧一簣。不同測試環...

資料結構與演算法2 時間複雜度和空間複雜度

演算法效率的度量方法 事後統計的方法 事前分析估算方法。演算法的時間複雜度 在進行演算法分析時,語句總的執行次數t n 是關於問題規模n的函式,進而分析t n 隨n的變化情況並確定t n 的數量級。演算法的時間複雜度記作 t n o f n 它表示隨問題規模n的增大,演算法執行時間的增長率和f n ...