標籤:
http://blog.sina.com.cn/s/blog_61bebe480100v7c7.html
基本的C++演算法分為三類:排序演算法、樹演算法、圖演算法
演算法思想有三種:遞推、分治、動態規劃 以及 貪心演算法。本文將簡要介紹上面三類演算法,介紹時穿插介紹演算法思想。 一、排序演算法 1、基本O(n^2)排序演算法: (對基本排序演算法的時間複雜度分析主要考慮 比較次數、資料交換次數)冒泡排序:針對數組、本地排序、需要交換資料。O(1)額外空間選擇排序:一般針對數組、本地排序、需要交換資料。O(1)的額外空間插入排序:可以是針對數組的本地排序,此時需要移動大片資料,但是比較次數是O(N*logN)。如果是針對鏈表,比較次數是O(N^2),但是不需要交換資料。 注意:一般排序都是針對數組的本地排序,數組與鏈表相比,可以隨機訪問,空間使用效率更高(鏈表需要存放指標),而鏈表一般對於插入與刪除操作有更好的效能。 2. O(N*logN)演算法快速排序:針對數組的本地排序,時間複雜度平均O(N*logN),最壞時O(N^2)。空間複雜度O(1)歸併排序:可以針對數組,也可以針對鏈表。針對數組時時間複雜度為O(N*logN),空間複雜度為O(N) 3. 堆排序1991年電腦先驅獎獲得者、斯坦福大學電腦科學系教授羅伯特·弗洛伊德(Robert W.Floyd)和威廉姆斯(J.Williams)在1964年共同發明了著名的堆排序演算法( Heap Sort )堆是一種非常高效的資料結構,可以用數組來表示堆。 堆排序是針對數組的本地排序,時間複雜度為O(N*logN),空間複雜度為O(1) 對於降序排列時用最小堆,首先建立堆,然後將第一個元素(堆頭)與組後一個元素交換。找到了排列的最後一個元素,然後再調整前N-1個元素為最小堆,依次類推,即完成排序。 注意:堆得建立, 堆的建立的時間複雜度為O(N*logN),可以有多種方法建立堆 4. 基數排序資料的取值範圍不大,利用bitmap 5. 外排序歸併排序,多路歸併排序(利用堆實現多路歸併排序)使用堆進行多路排序時,堆中的每個元素同附加上一個域,存放該元素來自那一路 堆一般還可以用於TopK演算法,求TopK最大可以使用K個元素的最小堆維護K個最大元素,對原始數組掃描一遍即可。 二、樹的演算法樹一般用鏈表實現,通常用樹資料結構實現資料的快速插入、刪除、尋找。 1. 平衡二叉尋找樹RB-Tree、 AVL、 Treap、 伸展樹(無需存放額外資訊) 2. B樹用於建立檔案系統或資料庫的索引。B樹的設計目標是減少IO訪問次數。B樹也是一棵平衡樹 3. 二項樹、二項堆、費波那奇堆 三、圖的演算法1. 圖的表示有向圖、無向圖 的 鄰接表表示、矩陣表示 2. 廣度優先搜尋、深度優先搜尋廣度優先搜尋(BFS):找到從單個源點到所有點得
最短路徑,適用於有向圖、無向圖。演算法發雜度為O(V+E),注意演算法對應圖的邊沒有權重。演算法使用隊列實現廣度優先。演算法使用三個輔助變數、color、paraent、distance數組。搜尋後的parent構成廣度優先樹 深度優先搜尋(DFS):可以隨意從一個節點開始,遍曆樹的所有節點,使用於有向圖、無向圖。搜尋構成森林。演算法通過遞迴方式實現,依次遞迴完成後可能只搜尋整個連通樹的部分節點,因此需要從新任意選擇一個節點從新開始DFS,整個搜尋結果構成搜尋森林。演算法使用三個輔助變數:color,v,f。v表示搜尋到該節點時間,f表示該節點的鄰接節點都掃描完成的時間。 注意DFS可以完成拓撲排序。利用f出現時間的降序就是拓撲序,可以在深度優先搜尋的過程中得到該排序。DFS演算法還可以用於發現強連通分支。 3. 最小產生樹 針對無向連通圖的,常見的演算法有 Kruskal演算法和Prim演算法 Kruskal演算法將所有的邊非降序排列,所有的頂點初始化為不相交集合,每次取一個邊,如果該邊屬於不同的集合,則該邊加入解集,同時更新不想交集合。注意:不想交集合實現有專門的資料結構。 Prim演算法該演算法與Dijkstra演算法類似,每次加入已覆蓋集合A和未覆蓋集合B之間最短的邊。 4. 最短路徑 有權值的最短路徑問題。可以是有向圖,可以是無向圖。權值可以為負值。 變種:點與點之間最短路徑、固定終點最短路徑、所有點之間最短路徑、最長路徑(將權值去負值利用bellman-ford演算法即可) Bellman-Ford演算法驚醒V-1遍鬆弛遍曆,每次遍曆,按照一定順序,依次將所有的邊鬆弛一遍。結束後,對所有的邊進行一次check,如果有邊不符合鬆弛條件,則返回false,表明圖中存在負權值的環(該特性可以用於檢測有向圖中得環),演算法複雜度O(VE) Dijkstra演算法只能針對於正值的邊。演算法複雜度O(V^2) 5. 求所有點之間的最短路徑矩陣上得動態規划算法。Floyd-Warshall演算法,d_ij(k) 表示從頂點i到頂點j,中間節點只包含{1、2、... k}的最短路徑。d_ij(n)即為所求。Floyd-Warshall演算法可以用於求任意兩個頂點是否可達
C++演算法之——常用演算法總結