由於缺乏對演算法和資料結構的知識,因此即便會用程序解決一些事情,但是對比專業的人員還是相差很大。如果可以了解演算法和熟悉運用資料結構,那麼對於後續的編寫程式會有很大的提升,因此即便是自學,也可以不落下這一塊的內容
演算法的簡單概念
輸入 + 演算法 = 輸出
設計演算法需要很嚴格的定義,但是對於演算法本身的定義卻是比較含糊的,對於入門的我來說,知道上面一個簡單的公式即可。
如何衡量演算法的好壞
- 時間緯度(時間複雜度)
- 記憶體緯度(空間/內存)
由於現在cpu比記憶體珍貴很多,因此我們優先考慮時間緯度。
好的演算法 = 步驟少 + 空間佔用少
演算法的時間緯度符號很多,但目前用的多的是大O,所以入門暫時就把心思花在這裏吧。
另外執行的情況都是在最糟糕的情況下來算n。
常見的六種時間複雜度與演算法
- O(1):陣列讀取(list讀取)
- O(n):簡易搜索
- O(log n ):二分搜索
- O(nlogn):合併排序
- O(n^2):選擇排序/插入排序
- O(2^n):斐波那契數列
資料結構基礎知識
摘自《我的第一本算法書》,用於回憶學習用
鏈表
優點:增加和刪除快(只需時間O(1)),只需要改變指針即可
缺點:訪問慢(時間緯度O(n))
種類:單向鏈表,雙向鏈表,環形鏈表
特點:分散存儲於內存中,訪問則需要按照順序訪問。
數組
優點:訪問快(O(1)),直接通過下標訪問如:array[1]
缺點:創建和刪除慢(O(n))
棧
特點:後進先出(LIFO),只能操作一端的數據,如若需要訪問其他層,需要調換順序,在只需要訪問最新數據時,使用棧就比較方便了.
入棧(push),出棧(pop)
舉例:規定(AB(C(DE)F)(G((H)IJ)K))這一串字符中括號的處理方式如下:
首先從左邊開始讀取字符,讀到左括號就將其入棧,讀到右邊括號就將棧頂的左括號出棧。此時,出棧的左括號便於當前讀取的右括號相匹配。
通過這種方式,我們就能得知配對括號的具體位置。
ps:在深度優先搜索算法中,通常會選擇最新的數據作為候補頂點。在候補頂點的管理上就可以使用棧.
隊列
特點:先進先出(FIFO),添加和刪除操作可以在兩端,添加操作(入隊),刪除操作(出隊)
ps:廣度優先搜索法中,通常就會從搜索候補中選擇最早的數據作為下一個頂點。此時,在候補頂點的管理上就可以使用隊列了。
哈希表
特點:類似於python中的字典,採用key-value的方式;
大概計算原理:假如有5個存儲位置,我們需要存儲每個名字和名字對應的性別;則我們可以根據名字(joy)計算出哈希值(通過哈希函數計算),
得到哈希值後,繼續採用mod運算,得到餘數,把該joy的數據存到該餘數的位置。
若存儲過程中,有多個數據餘數一樣(即是發生衝突),則可以採用鏈表存儲(鏈地址法),也可採用開放地址法(計算出一個/n個候補位置)
堆
結構規則:
- 子節點必定大於父節點(頂部的為父節點)
- 最小值被存在頂點
- 添加數據時,會把新數據放在最下面一行靠左的位置(然後於父節點對比,小於父節點則交換位置)
- 取出最小值後,把最後一行,最右側的數據提升到最上方,同時與左右子節點對比(與較小的值換位置)
時間複雜度: - 取最小值(O(1))
- 數據重構時間(O(logn))
二叉查找樹
結構規則:
- 左邊子節點均比父節點小,右邊子節點均比父節點大
- 查找最小值(從頂端開始,往左下最底端查找)
- 查找最大值(從頂端開始,往右下最底端查找)
- 添加數據(不斷的與父節點對比,< 則往左,>則往右
- 刪除數據(若在最底端,則直接刪除;若只有一個子節點,則刪除後子節點往上移;若存在兩個子節點,則把左樹中最大節點(或者右樹中最小節點)移動到被刪除的節點
時間複雜度:
節點若較為均衡,則為O(log(n)),最壞的情況為O(n),
以二叉查找樹為基礎拓展的平衡二叉查找樹(B樹)則是為了提高查找效率而做的數據結構