前端要不要學習資料結構
作為一名IT技術人員,需要不斷的完善自己的知識體系來提升自己,類似資料結構、網路等。在工作中大部分時間我們都是做應用層面的開發,有時候對資料結構、演算法這些基本功要求不是很高,但是一些基本得知識點我們還是需要掌握。
到底什麼是資料結構
是不是經常聽別人說資料結構、演算法、程式 = 資料結構 + 演算法等,那麼到底什麼是資料結構?
資料結構本身是一個抽象的概念,沒有具體的標準,比如我們用的電腦,我可以說電腦這種結構由cpu、主機板、顯示卡、記憶體、硬碟、電源、音效卡、網路卡等組成。如 vue-cli 初始化的專案由 main.js、src等組成。所以不需要去糾結到底什麼是資料結構,資料結構本身只是一層抽象的概念,從字眼上可以理解為資料與資料之間存在一種或多種關係的資料元素集合。
從不同的角度,資料結構可以理解為邏輯結構、物理結構。可以理解為邏輯結構是在計算機中的儲存形式,物理結構是計算機怎麼儲存資料;
邏輯結構:資料元素之間的相互關係
- 集合結構 平等關係,在同一個集合中
- 線性結構 一對一關係
- 樹形結構 一對多關係
- 圖形結構 多對多關係
物理結構:資料的邏輯結構在計算機中的儲存形式
- 順序儲存 類似連續的一個列表
- 鏈式儲存 存在一個指標指向需要的元素
演算法
解決問題的步驟我們叫方法,在計算機中稱演算法,在計算機中表現為指令的有限序列;通常一個問題有很多種方法,有些方法很巧妙,有些看起來比較繞,這些方法是有差異的,我們通常在計算機中通過時間複雜度、空間複雜度來衡量一個演算法的好壞。
時間複雜度
時間複雜度並不是說程式碼執行的具體的時間,而是表示程式碼執行時間隨問題規模或者資料規模增長的變化趨勢,也叫漸進時間複雜度,簡稱為時間複雜度。我們都知道一個演算法花費的時間與演算法中語句的執行次數肯定成正比例,哪一個演算法中語句執行次數多,它花費時間就多。
1 function get (n) { 2 let i = 0; // 一次 3 let name = '' // 一次 4 } 5 // 總共就是2次
如上所示,總共執行了2次,但是通常我們處理的事情這個n 可能不是一個固定值,所以我們把一個演算法中的語句執行次數記為函式T(n),n為問題規模,隨著問題規模n的變化,演算法執行的時間也會變化,為了更好的分析這個時間的變化比,用O()來表示時間複雜度的記法,我們稱為大O記法。語句執行總的次數T(n)跟O() 有如下公式
T(n) = O(f(n)),它表示隨著問題規模n 的增大,演算法執行時間的增長率和f(n)的增長率相同,其中f(n)是問題規模n的某個函式
大O推導方法
我們一般通過以下方法來分析一個演算法的時間複雜度
- 用常數1代替執行中的所有的加法常數
- 在修改後的執行次數函式中,只保留最高階項
- 如果最高階項存在且不為1,則去除與這個項相乘的常數(除法也是變相的相乘)
常數階:O(1)
如果演算法執行所需要的臨時空間不隨著某個變數n的大小而變化,即此演算法空間複雜度為一個常量,可表示為O(1)
1 function run () { 2 let value = 100 3 value += 10 4 console.log(value) 5 // 共執行3次,根據大O 推導法,把常數換成1,則結果是O(1) 6 }
線性階:O(n)
1 function run (n) { 2 for(let i = 0; i < n; i++) { 3 console.log(i) 4 } 5 } 6 // 共執行n次,根據大O推導法,只取最高階,所以是 O(n)
平方階__O( n^2 )
function run (n) { for(let i = 0; i < n ; i++ ) { for(let j = 0; j < n ; j++ ) { console.log(j) } } } /* 外層i的迴圈執行一次,內層j的迴圈就要執行n次 因為外層執行n次,那麼總的就需要執行n*n次, 也就是需要執行n^2次,根據大O推導法:O(n^2)
*/
常見的複雜度
執行次數 | 複雜度 | 非正式術語 |
12 | O(1) | 常數階 |
2n+3 | O(n) | 線性階 |
4n2+zn+2 | O(n2) | 平方階 |
4log2n+21 | O(logn) | 對數階 |
3n+2log3n+15 | O(nlogn) | nlogn階 |
4n3+3n2+22n+11 | O(n3) | 立方階 |
2n | O(2n) | 指數階 |
時間複雜度耗費時間從小到大依次排列
O(1) < O(logn) < O(n) < O(nlogn) < O(n2) < O(n3) < O(2n) < O(n!) < O(nn)
練習
1 function run(n) { 2 for (let i = 0; i < n; i++) { 3 for (let j = i; j < n; j++) { 4 console.log(`${n},hello word`) 5 } 6 } 7 } 8 run(10)
當 i = 0 時,內迴圈執行 n 次運算,當 i = 1 時,內迴圈執行 n - 1 次運算……當 i = n - 1 時,內迴圈執行 1 次運算。
所以,執行次數 T(n) = n + (n - 1) + (n - 2)……+ 1 = n(n + 1) / 2 = n^2 / 2 + n / 2。
根據上文說的 大O推導法 可以知道,此時時間複雜度為 O(n^2)。
空間複雜度
演算法的空間複雜度通過計算演算法所需的儲存空間,公式記住 S(n) = O(f(n)),其中n 為問題規模,f(n)為關於n 所佔儲存空間的函式。
資料結構與演算法的關係
資料結構和演算法是相輔相成的,雖然可以單獨分開為兩個東西,但是對於計算機來說把他們分開,那麼他們將變得十分無聊。
資料結構研究的是組織資料的方式,比如陣列,他就是一種組織資料的方式,就是一種資料結構。但是有了資料結構,不一定有演算法。資料結構是演算法的基礎,比如資料結構為陣列,使用陣列,可以寫出冒泡、快排等演算法。
資料結構為演算法服務,演算法作用在特定的資料結構之上。