數據結構與算法初步認識

文章來源:http://blog.seclibs.com/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%88%9D%E6%AD%A5%E8%AE%A4%E8%AF%86-2/算法

什麼是數據結構和算法數據結構

數據結構和算法常常是結合在一塊兒的東西,數據結構是數據的存儲方式,而算法是對數據的具體操做,他們兩者是相輔相成的,數據結構是爲算法服務的,算法是要做用在特定的數據結構之上的,二者是不能夠孤立存在的。數據結構和算法

在平時咱們所遇到的數據結構和算法有如下一些 函數

整個列表的內容下來仍是很是多的,這裏不立什麼flag,只是爲了給以後所學習的內容作一個更好的鋪墊。學習

數據結構和算法的應用就是爲了解決程序的快和省的問題,即運行的夠快,佔用的空間夠少,在評比這兩項內容的時候,咱們引入了時間複雜度和空間複雜度兩個複雜度的概念。雖說咱們能夠在寫完程序後對程序的時間進行計算和統計等,但那屬於過後統計法,有一種過後諸葛亮的感受,咱們須要的是在寫程序的時候就對總體的複雜性有一個大概的評估。code

這裏咱們引入的是大O表示法,T(n)=O(f(n)),其中,T(n) 表示代碼執行的時間;n 表示數據規模的大小;f(n) 表示每行代碼執行的次數總和。由於這是一個公式,因此用 f(n) 來表示。公式中的 O,表示代碼的執行時間 T(n) 與 f(n) 表達式成正比。blog

而後咱們先來講時間複雜度分析,在進行分析的時候,咱們只關注跟規模n有關的內容,其他的內容咱們默認它們的時間複雜度爲O(1),好比get

int a=1;

int b=2;

int c=3;

這類型的代碼無論在程序有多少,即便是成千上萬行,由於它們的數量是固定的,若是在n爲無窮大的時候,它們也就能夠忽略不計了,因此咱們認爲它們的時間複雜度爲O(1),在計算的時候就能夠忽略掉這部份內容了。cli

那若是是一個簡單的循環語句的話,它的時間複雜度就爲O(n)file

int sum = 0;

int i = 1;

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

sum = sum + i;

}

由於前面的賦值語句在後面的循環的複雜度面前就能夠忽略不計了,因此只須要看循環執行的次數便可。

若是是多個語句結合在一塊兒的話就須要仔細進行分析

int cal(int n) {
int sum_1 = 0;
int p = 1;
for (; p < 100; ++p) {
sum_1 = sum_1 + p;
}

int sum_2 = 0;
int q = 1;
for (; q < n; ++q) {
sum_2 = sum_2 + q;
}

int sum_3 = 0;
int i = 1;
int j = 1;
for (; i <= n; ++i) {
j = 1; 
for (; j <= n; ++j) {
sum_3 = sum_3 + i * j;
}
}

return sum_1 + sum_2 + sum_3;
}

對於這樣的代碼,咱們能夠很清楚的分析出來,三段代碼的時間複雜度依次是O(1)、O(n)、O(n²),但由於它們是一個總體的存在,咱們選取它們其中最大的一個時間複雜度來做爲這段代碼所須要的時間複雜度,即O(n²)。

接着咱們再來看一段代碼

int cal(int n) {
int ret = 0; 
int i = 1;
for (; i < n; ++i) {
ret = ret + f(i);
} 
}

int f(int n) {
int sum = 0;
int i = 1;
for (; i < n; ++i) {
sum = sum + i;
} 
return sum;
}

在這段代碼中,咱們先看cal函數,若是把f()操做做爲一個簡單操做,那麼它的時間複雜度爲O(n),可是f()操做自己的時間複雜度爲O(n),因此總體的時間複雜度須要將兩個相乘,爲O(n²)

緊接着在來一段相似的代碼

i=1;
while (i <= n) {
i = i * 2;
}

這段代碼看起來跟剛開始說的循環沒有太大的卻別,可是仔細分辨一下,就會發現不一樣

若是將i從1開始循環,每次都會將i的值乘2,最後跳出循環的條件應該爲2x=n (2的x次方),只要咱們求出來x的大小也就知道了這個它的時間複雜度,即O(log2n)(log以2爲底,n的對數)

到這裏,也就基本能理解時間複雜度的計算方法了

而後來講一下咱們常見的幾種時間複雜度

在這些時間複雜度中,能夠粗略的將它們分紅兩類,多項式量級和非多項式量級,非多項式量級只有圖中畫波浪線的兩種,當數據規模n愈來愈大時,非多項式量級的執行時間將會急劇增長,就是咱們所謂的指數級爆炸式增加,因此它們的算法是很是低效。

除了上面提到的幾種時間複雜度外,還有一種由多個數據規模同時決定的複雜度

int cal(int m, int n) {
int sum_1 = 0;
int i = 1;
for (; i < m; ++i) {
sum_1 = sum_1 + i;
}

int sum_2 = 0;
int j = 1;
for (; j < n; ++j) {
sum_2 = sum_2 + j;
}

return sum_1 + sum_2;
}

能夠很容易的看出,第一個的時間複雜度爲O(m),第二個時間複雜度爲O(n),後面將兩個函數的值相加,咱們沒法輕易的選取其中的一個時間複雜度做爲整個模塊的時間複雜度,因此它們的時間複雜度爲O(m+n)

到這裏時間複雜度也就基本說完了,接着說一下空間複雜度的相關內容

這裏能夠經過類比的方式來講空間複雜度,時間複雜度是執行時間和數據規模之間的增加關係,那麼空間複雜度就是存儲空間和數據規模之間的增加關係,咱們常見到的空間複雜度也就只有 O(1)、O(n)、O(n²)三種,像 O(logn)、O(nlogn) 等通常都是用不到的,因此掌握了時間複雜度的計算方法對空間複雜度也就有大體瞭解了。

文章首發公衆號:無意的夢囈(wuxinmengyi)

這是一個記錄紅隊學習、信安筆記,我的成長的公衆號

掃碼關注便可

file

相關文章
相關標籤/搜索