《啊哈!演算法》
零零散散花了一周的時間閱讀了《啊哈!演算法》。這本書內容相對基礎,適合初學者時閱讀(當然,大神也可以溫故而知新)。《啊哈!演算法》這本書中的演算法舉例貼近生活,語言詼諧幽默,不會讓人產生枯燥感,並配有很多幽默的插圖。演算法講解通俗易懂,並配有詳細c語言**和注釋,是一本初學者不易錯過的好書。注:書作者偶爾會在書中賣萌的。已掌握的知識點在下面不在贅述,只記錄覺得需要記憶整理的東西,作為自己的讀書筆記。包括一些小技巧、新概念、生疏演算法等。內容仍比較雜亂,需要進一步細化整理。
來兩張配圖
快排:
氣泡排序:
《啊哈!演算法》中涉及的資料結構有棧、佇列、鍊錶、樹、並查集、堆和圖等;涉及的演算法有排序、列舉、深度和廣度優先搜尋、圖的遍歷,當然還有圖論中不可以缺少的四種最短路徑演算法、兩種最小生成樹演算法、割點與割邊演算法、二分圖的最大匹配演算法等。
第一章 排序
桶排序、氣泡排序、快速排序
1.當需要對5個人的名字和分數排序: 名字
huhu
haha
hengheng
gaoshou
xixi分數
使用簡單的桶排序只能對分數進行排序,如何找分數對應的人呢?
可以使用」結構體+排序演算法」解決
struct student
2.快速排序中
待排矩陣為a:61
2793
45108
如果設定基準數是最左邊的數,最左邊的哨兵為i,最右邊的那麼需要哨兵j先走。因為這樣才能保證最後哨兵i和
j相遇的時候,
a[i]=a[j]>=a[1]
。這樣與
a[j]
與a[1]
交換後才滿足快排演算法分組要求,哨兵左邊的數小於等於哨兵,右邊的數大於等於哨兵。
3.數列去重並排序(只保留不同的數,並從小到大排序)
方法1:先去重,後排序
例:桶排序
去重**:
%init
for(i=1;i<=n;i++)
%printf
方法2:先排序,後去重
例:氣泡排序
去重**:
%sort
for(i=2;i<=n;i++)
第二章 棧、佇列、鍊錶1.佇列的隊首head和隊尾的下乙個位置
tail
問題:為什麼tail不直接記錄隊尾?
答:隊首和隊尾重合時會帶來一些麻煩。我們規定隊首和隊尾重合時,隊列為空。(其實也可以直接記錄隊尾,依據自己情況而定)
2.棧解密回文很方便
3.鍊錶
鍊錶的另一種表現形式(不用指標,陣列形式實現)
模擬鍊錶:陣列data儲存序列中的每乙個數,陣列
right
存放序列中每乙個數右邊的數是誰
如果要表示鍊錶2->3->4->8->9->10->18->26->32
data2
3 4
8 9
10 18
26 32
right2
3 4
5 6
7 8
9 0
如果在8
的前面插入6,
2->3->4->
6->8->9->10->18->26->32
那麼陣列修改
:注:right[0]
表示右邊沒有元素
data2
3 4
8 9
10 18
26 32
6 right2
3 10
5 6
7 8
9 0
4
第三章 列舉
1.暴力列舉問題
可以思考是否可以採用深度優先搜尋(dfs)和廣度優先搜尋(
bfs)代替,從而簡化演算法。
第四章 搜尋
深度優先搜尋和廣度優先搜尋
1.深度優先搜尋基本模型
void dfs(int step)返回}
2.floodfill漫水填充法(也稱種子填充法)
3.dfs與
bfs時間複雜度都是o(|v| + |e|),其中
|v|是節點的數目,而|e|是圖中邊的數目。
第五章 圖
1圖是一種比線性表和樹更為複雜的資料結構
線性表:元素之間是線性關係,即表中元素最多乙個直接前驅和乙個直接後繼。
樹:元素之間是層次關係。除根外,元素只有唯一直接前驅,但可以有若干個直接後繼。
。 注意:實際上,樹是圖的特列---有向無環圖
2.圖的鄰接矩陣儲存法和鄰接表儲存法
第六章 最短路徑
最短路徑演算法對比分析
floyd
dijkstra
bellman-ford
佇列優化的bellman-ford
空間複雜度
o(n^2)
o(m)
o(m)
o(m)
時間複雜度
o(n^3)
o((m+n)logn)
o(nm)
最壞是o(nm)
適用情況
1.稠密圖
2.和頂點關係密切
1.稠密圖
2.和頂點關係密切
1.稀疏圖
2.和邊關係密切
1.稀疏圖
2.和邊關係密切 負權
可以解決負權
不能解決負權
可以解決負權
可以解決負權
注:其中n表示點數,
m表示邊數
floyd演算法雖然總體時間複雜度,但是可以解決負權邊(不能解決負權環,實際上這幾種都無法解決負權迴路,因為一直迴圈下去總能找到更小的路徑),並且均攤到每一點對上,在所有的演算法中還是比較好的. floyd演算法**複雜度小也是一大優勢. dijkstra演算法最大的弊端就是無法適應有負權邊的圖,但dijkstra具有很好的可擴充套件性,另外在dijkstra演算法在選擇剩餘不在最短路徑頂點的集合中選擇最小值是可以堆優化,這樣演算法的時間複雜度可以達到o(mlogn). 當圖中含有負邊時,使用bellman-ford或者佇列優化的bellman-ford演算法.
第七章 樹
1.樹其實就是不含迴路的無向圖
2.堆是一種特殊的特殊的完全二叉樹
3.優先佇列:支援插入元素和尋找最大(小)值元素的資料結構。
如果使用普通佇列來實現這個兩個功能,那麼尋找最大元素需要列舉整個佇列,這樣的時間複雜度比較高。如果已排序好的陣列,那麼插入乙個元素則需要移動很多元素,時間複雜度依舊很高。而堆就是一種優先佇列的實現,可以很好的解決這兩種操作。
4.堆還經常被用來求
乙個數列中第k大的數。只需要建立乙個大小為k的最小堆,堆頂就是第k大的數。如果求乙個數列中第k小的數,只最需要建立乙個大小為k的最大堆,堆頂就是第k小的數,這種方法的時間複雜度是o(nlogk)。當然你也可以用堆來求前k大的數和前k小的數。
5.並查集是一種樹型的資料結構,用於處理一些不相交集合(disjoint sets)的合併及查詢問題。常常在使用中以森林來表示。
1.最小生成樹
kruskal演算法是一步步地將森林中的樹進行合併,而
prim
演算法則是通過每次增加一條邊來建立一棵樹
kruskal演算法適用於稀疏圖,沒有使用堆優化的
prim
演算法適用於稠密圖,使用了堆優化
prim
演算法則適用於稀疏圖。
2.圖的割點與割邊
3.二分圖最大匹配
第九章 還能更好嗎——微軟亞洲研究院面試
《啊哈!演算法》筆記
第 1 章 排序 桶排序 氣泡排序 快速排序 第 2 章 棧 佇列 鍊錶 佇列 棧 鍊錶 模擬鍊錶 第 3 章 列舉!很暴力 奧數數的全排列 第 4 章 萬能的搜尋 深度優先搜尋 廣度優先搜尋 第 5 章 圖的遍歷 深度和廣度優先 圖的深度優先遍歷 圖的廣度優先遍歷 第 6 章 最短路徑 第 1節 ...
排序演算法讀書筆記
按關鍵字相等的記錄順序是否變化,分為穩定和不穩定 按儲存器不同分為內部排序和外部排序,外部是指數量很大,記憶體一次不能容納全部記錄,要訪問外存 按複雜度分簡單排序 普通排序和基數排序 按依據的原則不同分為插入排序 交換排序 選擇排序 歸併排序和計數排序。排序通常需要兩種操作 比較 移動記錄。1 平均...
讀書筆記 演算法導論
第2章演算法入門 浮於表面不如深入其中,送給自己,自己是最大的敵人,那麼就盡最大努力去克服自己,沉思,冷靜,不浮躁!勘誤 在演算法導論第9頁,扼要的扼 內容提要 1 偽 的表示方法 2 插入排序演算法分析 3 迴圈不變式 4 演算法設計之分治法 divide and conquer 5 合併排序演算...