資料結構和演算法 複雜度分析

2021-09-05 01:24:57 字數 3992 閱讀 7033

演算法的執行效率,粗略的講就是演算法的執行時間,那麼如何在不執行**的情況下,估算**的執行時間呢

我們先看乙個簡單的求和**

1 int cal(int n) 

7 return sum;

8 }

從cpu的角度來看,每一行**都做著相同的工作,讀資料-計算-寫資料,儘管每行**對應的cpu的執行個數,執行時間都不一樣,但是我們還是粗略的估算,所以假設每一行**都執行了base_time的時間,在這個假設基礎上,這段**執行了多少時間呢

第2和3行分別執行了一次,共用了2base_time的時間,4和5行分別執行了n次,用了2nbase_time的時間,我麼可以計算出,**執行的總時間是(2n+2)*base_time,可以看出所有**的執行總時間t(n)和每行**的執行的次數成正比。

按照這個思路,我們來分析一下,下面的**

1 int cal(int n) 

10 }

11 }

我們看出,2,3,4行分別執行一次,5,6行分別執行n次,7,8行分別執行n2次,這段**一共執行 3+2n+2n2次,所以總**的執行時間t(n)=(3+2n+2n2)*base_time;

我們雖然不知道base_time的具體數值,但是通過這倆段**的推斷過程,我們知道了乙個規律,所有**的總執行時間t(n)與每行**執行次數n成正比

我們可以把規律總結成乙個公式

t(n)=o(f(n));
t(n):表示執行的總時間

n :表示資料規模的大小

f(n) :表示**執行的總次數

o:表示t(n)和f(n)成正比

所以第一段**我們可以表為 t(n)=o(2n+2),第二段**可以表示為t(n)=o(22+2n+2)這就是大o複雜度表示法,大o時間複雜度並不代表**的真正執行時間,而是**執行時間隨資料規模增長的變化趨勢所以也叫漸進時間複雜度,簡稱時間複雜度

當n很大時,我們當做1000,10000甚至更大,這個是時候低階,常量,係數並不左右增長趨勢,都可以忽略,只需要記乙個最大量級就可以了,所以上面兩端**複雜度可以改為 t(n)=o(n),t(n)=o(n2)

上面介紹了大o表示法,下面我們來看一下如何分析時間複雜度

1 只關注迴圈次數最多的那段**

我剛才說了,大 o 這種複雜度表示方法只是表示一種變化趨勢。低階,常量,係數並不左右增長趨勢,都可以忽略,只需要記乙個最大量級就可以了,所以我們在分析一段**,或乙個演算法的複雜度的時候,只需要關注迴圈次數最多的那一段**就可以了。這段核心**執行次數的 n 的量級,就是整段要分析**的時間複雜度

我們來看乙個例子

int cal(int n) 

return sum;

}

我們可以看到2,3行常量級的執行時間,和n的趨勢無關可以忽略,迴圈最多的是4,5行**,這塊我們要重點分析,這兩行**被執行了n次,所以時間複雜度就是o(n)

2 加法法則,總複雜度等於量級最大的那段**的複雜度

我們來看一段**

int cal(int n) 

int sum_2 = 0;

int q = 1;

for (; q < n; ++q)

int sum_3 = 0;

int i = 1;

int j = 1;

for (; i <= n; ++i)

}return sum_1 + sum_2 + sum_3;

}

這段**有三個部分 分別是 sum_1 ,sum_2,sum_3,我們分析一下這三部分的時間複雜度,第一部分迴圈了100次,是乙個常量級的,這裡需要強調一下,只要是乙個確定的數,不管是100還是1000000,都認為是乙個常量級的數字,當n無限大的時候都可以忽略,第二段和第三段的時間複雜度是o(n)和o(n2),綜合這三段複雜度,我們只取最大量級的,所以整段複雜度就是o(n2),也就是說,總的時間複雜度就是最大量級的時間複雜度3 乘法法則,巢狀**的複雜度,等於巢狀內外**複雜度的乘積例如上方sum_3 就是內外的乘積 n*n=n2

1 常量階o(1)

常量階並不是指的是一行**,只要**的執行時間不隨n的增大而增大,這樣的**時間,我們就稱作o(1),一般情況下只要**中不存在,迴圈,遞迴語句,即使是成千上萬行**也是o(1);

2 對數階o(logn)和o(nlogn)

i=1;

while (i <= n)

我們來算一下這個的時間複雜度

我們按照上面的方法去分析,我們可以看出第三行是迴圈次數最多的地方,所以我們計算出第三行的執行次數就可以算出時間複雜度

從**上可以看出i從1開始,每次乘以2,當大於n時迴圈結束,其實i的取值是乙個等比數列,如下

所以我麼只要知道x是多少,就知道了執行的次數,那麼求解2x=n,x=㏒❷n,時間複雜度就是o(log2n);

實際上不管以2為底,害死以3為底,以10為底,都統一計作logn

3 o(m+n),o(m*n)

int cal(int m, int n) 

int sum_2 = 0;

int j = 1;

for (; j < n; ++j)

return sum_1 + sum_2;

}

我們可以看到上方分為2個規模,m和n,由於不能判斷出m和n的規模大小,所以我們在計算的時候就不能簡單利用加法法則,忽略掉乙個,所以上方的複雜度就是o(m+n)

最好時間複雜度和最壞時間複雜度

/**

* @param arr

* @param n 表示array的長度

* @param x 表示查詢的數字

* @return x 的下標

*/private int find(int arr, int n, int x)

}return postion;

}

上面這段**的時間複雜度是多少呢,是o(n)嗎?

我們分析一下,當x在陣列第乙個的時候,我們就不需要遍歷剩下的(n-1)個,那麼時間複雜度就是o(1),假如x不存在陣列中,那麼就需要遍歷n次,那麼時間複雜度就是o(n),在不同的情況下時間複雜度不同,所以我們要引入,最好時間複雜度和最壞時間複雜度

最好時間複雜度:指的是,在最理想的情況下,這段**執行的時間複雜度,例如上面x存在陣列第乙個位置

最壞時間複雜度:指的是,在最糟糕的情況下,這段**執行的時間,例如上面x不存在陣列中

空間複雜度全稱,漸進空間複雜度,表示演算法的儲存空間和資料規模之間的關係

void print(int n) 

}

我們看下這段**

第二行申請了乙個空間儲存i,是常量級的可以忽略,第三行申請了n個空間,除此之外,其他**並沒有占用太多空間,所以這段**的空間複雜度是o(n)

我們常見的空間複雜度是o(1),o(n),o(n2),空間複雜度比較簡單,掌握這些就可以了

資料結構和演算法 複雜度分析

如何衡量 的效率?時間和空間複雜度分析。這個是資料結構和演算法的重中之重 資料結構和演算法的作用主要是用來解決 快 和 省 的問題。即如何讓 執行的更快,如何讓 更節省記憶體空間。執行效率是一項非常重要的考量指標。而我們可以時間 空間複雜度分析 的執行效率。事後統計法 我們可以跑一遍 通過統計 監控...

資料結構和演算法 複雜度

演算法複雜度 1 時間複雜度 表示演算法的執行時間與資料規模之間的增長關係 1 只關注迴圈執行次數最多的一段 2 加法法則 總複雜度等於量級最大的那段 的複雜度 3 乘法法則 巢狀 的複雜度等於巢狀內外 複雜度的乘積 幾種常見時間複雜度例項分析 最好 最壞 平均 均攤時間複雜度要根據具體的演算法進行...

1 1資料結構 演算法複雜度分析

1 演算法時間複雜度分析 1 原操作 定義語句 賦值語句 輸入輸出語句 即非迴圈 順序 分支等控制結構 2 頻度 tn 原操作執行的次數 4 演算法時間複雜度o n 頻度的數量級 5 問題規模n 把任何要解決的問題的輸入都轉化成乙個陣列,那麼陣列長度就是問題規模。6 o 1 即常數階,乙個演算法中沒...