目錄html
博客:blog.shinelee.me | 博客園 | CSDN算法
如何評估一個算法的計算時間?數據結構
一個算法的實際運行時間很難評估,當時的輸入、CPU主頻、內存、數據傳輸速度、是否有其餘程序在搶佔資源等等,這些因素都會影響算法的實際運行時間。爲了公平地對比不一樣算法的效率,須要脫離開這些物理條件,抽象出一個數學描述。在全部這些因素中,問題的規模每每是決定算法時間的最主要因素。所以,定義算法的時間複雜度\(T(n)\),用來描述算法的執行時間隨着輸入規模的增加將如何變化,增加速度是怎樣的。數據結構和算法
在輸入規模較小時,運行時間原本就少,不一樣算法的差別不大。因此,時間複雜度一般關注的是輸入規模\(n\)較大時運行時間的變化趨勢,稱之爲漸進複雜度,採用大O記號,表示漸進上界,對於任意的\(n >> 2\),如有常數\(c\)和函數\(f(n)\)知足
\[ T(n) \leq c \cdot f(n) \]
則記做
\[ T(n) = O(f(n)) \]
能夠簡單地認爲,\(O(f(n))\)表示運行時間與\(f(n)\)成正比,好比\(O(n^2)\)表示運行時間與輸入規模的平方成正比,這樣講雖然並不嚴謹,但通常狀況下無傷大雅。函數
在\(n\)很大時,常數\(c\)變得可有可無,不一樣算法間的比較主要關注\(f(n)\)部分的大小。好比,在\(n >> 100\)時,\(n^2\)要比\(100n\)大得多,所以重點關注\(n^2\)和\(n\)增加速度的差別便可。優化
不一樣時間複雜度的增加速度對好比下,圖片來自Big-O Cheat Sheet Poster,ui
除了大\(O\)記號,還有大\(\Omega\)記號和\(\Theta\)記號,分別表示下界和確界,
\[ \Omega(f(n)) : \ c\cdot f(n) \leq T(n) \\\Theta(f(n)) : \ c_1 \cdot f(n) \leq T(n) \leq c_2 \cdot f(n) \]
他們的關係以下圖所示,圖片截自鄧俊輝-數據結構C++描述第三版spa
下面彙總摘錄了經常使用數據結構操做和排序算法的複雜度,來源見引用。其中包含最壞時間複雜度、平均時間複雜度以及空間複雜度等,對於排序算法還含有最好時間複雜度。.net
附帶上連接:server
Array Stack Queue Singly-Linked List Doubly-Linked List Skip List Hash Table Binary Search Tree Cartesian Tree B-Tree Red-Black Tree Splay Tree AVL Tree KD Tree
Quicksort Mergesort Timsort Heapsort Bubble Sort Insertion Sort Selection Sort Tree Sort Shell Sort Bucket Sort Radix Sort Counting Sort Cubesort
以及Data Structures in geeksforgeeks。
漸進複雜度分析的是輸入規模較大時的狀況,輸入規模較小時呢?
在輸入規模較小時,就不能輕易地忽略掉常數\(c\)的做用,以下圖所示,圖片來自Growth Rates Review。複雜度增加快的在輸入規模較小時可能會小於複雜度增加慢的。
因此在選擇算法時,不能無腦上看起來更快的高級數據結構和算法,還得具體問題具體分析,由於高級數據結構和算法在實現時每每附帶額外的計算開銷,若是其帶來的增益沒法抵消掉隱含的代價,可能就會得不償失。
這同時也給了咱們在代碼優化方向上的啓示,
以上