演算法採用的策略、方案
編譯產生的**質量
問題的輸入規模
機器執行指令的速度
由此可見,拋開計算機硬體,乙個程式的執行時間依賴於演算法的好壞和輸入規模。
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 ...