在我們的編程之旅中,C語言為我們打下了堅實的基礎(chǔ)。然而,如今我們踏入了新的領(lǐng)域——數(shù)據(jù)結(jié)構(gòu)與算法
c語言系列文章大家可以瀏覽我的專欄:c語言學(xué)習(xí)
**那么現(xiàn)在就以算法的時間復(fù)雜度和空間復(fù)雜度開始,逐步探索這個數(shù)據(jù)結(jié)構(gòu)的精彩之處 **
一.算法效率
1.1 如何衡量一個算法的好壞
通常我們都會認為越簡短算法越好 ,但是我們在用遞歸實現(xiàn)求斐波那契數(shù)列的時候,代碼確實簡短,但是效率卻不高
int fib(int n) { if (n <= 2) { return 1; } else { return fib(n - 1) + fib(n - 2); } }
讓求個第50個耗費的時間就已經(jīng)不短了,所以我們需要一個統(tǒng)一的標準來衡量代碼的好壞——算法的復(fù)雜度
1.2 算法的復(fù)雜度
算法在編寫成可執(zhí)行程序后,運行時需要耗費時間資源和空間(內(nèi)存)資源 。因此衡量一個算法的好壞,一般
是從時間和空間兩個維度來衡量的,即我們所說的時間復(fù)雜度和空間復(fù)雜度
- 時間復(fù)雜度:時間復(fù)雜度描述了算法解決問題所需的時間量級。它表示隨著輸入規(guī)模的增加,算法執(zhí)行所需時間的增長趨勢,時間復(fù)雜度主要衡量一個算法的運行快慢
- 空間復(fù)雜度:空間復(fù)雜度衡量了算法在執(zhí)行過程中所需的額外內(nèi)存空間。表示隨著輸入規(guī)模增加,算法所需內(nèi)存的增長趨勢。空間復(fù)雜度主要衡量一個算法運行所需要的額外空間
而如今計算機的存儲容量已經(jīng)達到了很高的程度。所以我們?nèi)缃褚呀?jīng)不需要再特別關(guān)注一個算法的空間復(fù)雜度,更加著重于時間復(fù)雜度
二.時間復(fù)雜度
2.1基本概念
算法的時間復(fù)雜度是一個函數(shù),它定量描述了該算法的運行時間。一個算法執(zhí)行所耗費的時間,從理論上說,是不能算出來的,只有你把你的程序放在機器上跑起來,才能知道。顯然這很麻煩,所以才有了時間復(fù)雜度這個分析方式。
一個算法所花費的時間與其中語句的執(zhí)行次數(shù)成正比例,算法中的基本操作的執(zhí)行次數(shù),為算法的時間復(fù)雜度
確定一個算法中某個基本操作與問題規(guī)模 N 之間的關(guān)系式,即可確定該算法的時間復(fù)雜度
eg:計算一下test1中++count語句總共執(zhí)行了多少次?
#include<stdio.h> int test1(int N) { int count = 0; for (int i = 0; i < N; ++i) { for (int j = 0; j < N-1; ++j) { ++count; } } for (int k = 0; k < N; ++k) { ++count; } int M = 20; while (M--) { ++count; } } int main() { test1(); return 0; }
可以知道執(zhí)行的次數(shù)F(N)只與N有關(guān):
F ( N ) = N ? ( N ? 1 ) + N + 20 F(N)=N*(N-1)+N+20 F(N)=N?(N?1)+N+20
- N = 10 F(N) = 120
- N = 100 F(N) = 10020
實際中計算時間復(fù)雜度時,其實并不一定要計算很精確的執(zhí)行次數(shù),只需要知道大概執(zhí)行次數(shù),即使用大O的漸進表示法
2.2 大O的漸進表示法
大 O 漸進表示法(Big O notation): 是一種用于描述算法復(fù)雜度的數(shù)學(xué)表示方法。它用于衡量算法在最壞情況下執(zhí)行時間的上限,即算法的增長率
規(guī)則:
- 用常數(shù)1取代運行時間中的所有加法常數(shù)
- 在修改后的運行次數(shù)函數(shù)中,只保留最高階項
- 如果最高階項存在且不是1,則去除與這個項目相乘的常數(shù)。得到的結(jié)果就是大O階
上面的 F ( N ) = N ? ( N ? 1 ) + N + 20 F(N)=N*(N-1)+N+20 F(N)=N?(N?1)+N+20 用大O表示法為:
O ( N 2 ) O(N^2) O(N2)
通過上面這個例子會發(fā)現(xiàn)大O的漸進表示法去掉了那些對結(jié)果影響不大的項,簡潔的表示出了執(zhí)行次數(shù)
有些算法的時間復(fù)雜度也分最好,平均,最壞的情況:
- 最壞情況:任意輸入規(guī)模的最大運行次數(shù)
- 平均情況:任意輸入規(guī)模的期望運行次數(shù)
- 最好情況:任意輸入規(guī)模的最小運行次數(shù)
eg:在一個長度為n的整形數(shù)組arr里找a這個值
最好情況第一次就找到了 平均情況n/2次找到 最壞情況n次找的
在實際中一般情況關(guān)注的是算法的最壞運行情況,所以數(shù)組中搜索數(shù)據(jù)時間復(fù)雜度為O(N)
2.3常見時間復(fù)雜度計算
void test2(int N,int M)
{
int count = 0;
for (int k = 0; k < M; ++k)
{
count++;
}
for (int k = 0; k < N; ++k)
{
count++;
}
}
基本操作執(zhí)行了M+N次,時間復(fù)雜度為O(N)
void test3()
{
int count = 0;
for (int k = 0; k < 100; ++k)
{
++count;
}
}
基本操作執(zhí)行了100次(常數(shù)),時間復(fù)雜度為O(1)
void BubbleSort(int* a, int n)
{
assert(a);
for (size_t end = n; end > 0; --end)
{
int exchange = 0;
for (size_t i = 1; i < end; ++i)
{
if (a[i - 1] > a[i])
{
Swap(&a[i - 1], &a[i]);
exchange = 1;
}
}
if (exchange == 0)
break;
}
}
基本操作執(zhí)行最好N次,最壞執(zhí)行了(N*(N+1)/2次,通過推導(dǎo)大O階方法+時間復(fù)雜度看最
壞,時間復(fù)雜度為 O ( N 2 ) O(N^2) O(N2)
int BinarySearch(int* a, int n, int x)
{
assert(a);
int begin = 0;
int end = n - 1;
while (begin <= end)
{
int mid = begin + ((end - begin) >> 1);//相當于begin+(n/2)
if (a[mid] < x)
begin = mid + 1;
else if (a[mid] > x)
end = mid - 1;
else
return mid;//找到了返回下標
}
return -1;//沒找到返回-1
}
基本操作執(zhí)行最好1次,最壞O( log ? 2 N \log_2N log2?N)次,時間復(fù)雜度為 O( log ? 2 N \log_2N log2?N) (一般情況下寫成 l g N lgN lgN)
三.空間復(fù)雜度
3.1基本概念
空間復(fù)雜度也是一個數(shù)學(xué)表達式,是對一個算法在運行過程中臨時占用存儲空間大小的量度 。
空間復(fù)雜度不是程序占用了多少bytes的空間,算的是變量的個數(shù)。
空間復(fù)雜度計算規(guī)則基本跟實踐復(fù)雜度類似,也使用大O漸進表示法
3.2常見時間復(fù)雜度計算
void BubbleSort(int* a, int n)
{
assert(a);
for (size_t end = n; end > 0; --end)
{
int exchange = 0;
for (size_t i = 1; i < end; ++i)
{
if (a[i - 1] > a[i])
{
Swap(&a[i - 1], &a[i]);
exchange = 1;
}
}
if (exchange == 0)
break;
}
}
使用了常數(shù)個額外空間,所以空間復(fù)雜度為 O(1)
long long Fac(size_t N)
{
if(N == 0)
return 1;
return Fac(N-1)*N;
}
空間復(fù)雜度是 O(N),其中 N 是輸入的參數(shù)。這是因為每次遞歸調(diào)用都會在內(nèi)存中創(chuàng)建一個新的函數(shù)調(diào)用幀文章來源:http://www.zghlxwxcb.cn/news/detail-761726.html
好啦,今天的內(nèi)容梳理就先到這里了,下一次應(yīng)該會是順序表了。感謝大家支持!?。??文章來源地址http://www.zghlxwxcb.cn/news/detail-761726.html
到了這里,關(guān)于打開數(shù)據(jù)結(jié)構(gòu)大門:深入理解時間與空間復(fù)雜度的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!