從連結串列出發封裝一個自己的工具

weixin_34138377發表於2017-11-07

這個是第一篇, 說一下前提; 

前些時候用到cache的時候用到了YYCache來做快取, 然後裡面提到了一個快取演算法LRU, 然後快取演算法常見的有LFU、LRU、ARC、FIFO、MRU(百度百科); 其中LRU稱為 "最近最少使用演算法",這裡的增刪主要使用連結串列來實現, 因為連結串列的增刪都是O(1),(寫到這裡很慌, 希望沒有說錯, 不要被打臉)

這裡有點模糊, 所以來重新複習一下資料結構以及演算法, 都是實用的, 首先我找的資料呢是<<演算法第四版>>, 這個是java實現的 然後參考了一下其他資料. 好的作為一個iOS開發人員, 我們首先來看一下連結串列的swift怎麼實現

第一我們來實現一下連結串列

連結串列的swift實現

好了, 這裡說幾點, 第一這裡的連結串列是使用類來實現的, 並不是用結構體,裡面不能用儲存屬性, 而每一個節點我們都是這種儲存屬性, 這個用引用型別實現會比較好. 所以這裡選擇的是類, 而不是結構體.

第二步 我們用這個連結串列來實現一些基礎的資料結構棧和佇列和揹包

棧的連結串列實現

佇列的連結串列實現

揹包的連結串列實現

大家注意到, 用連結串列可以很方便的實現棧和佇列, 這裡用陣列也可以實現同樣的功能,具體的區別在於對應的操作的效率,大家可以自己對比一下, 我還是比較推薦用連結串列實現, 因為主要是增刪的操作對於連結串列是O(1), 對於陣列是O(n)

在構建這幾個基本的資料結構的時候呢, 用到了swift中關於迭代器和對列的相關協議.讓連結串列可以像陣列一樣用forin迴圈進行操作, 並且提供了快捷的構建方法, 通過陣列和字面量的兩種形式

LRU演算法: Least recently used,最近最少使用. 這個淘汰演算法是指將最近訪問過的資料插到最前面, 當超過限制之後從最後面刪除資料.好吧, 現在我們來用連結串列來實現這個演算法, 並且做一個能使在實際專案使用到的工具.

RLU演算法的連結串列實現

這裡的演算法實現也是通過包裝連結串列的一些列方法來實現的, 這裡需要討論的問題是, 那麼為什麼不直接用連結串列來實現這些功能而是用一個協議來實現, 這就是為了更好封裝性和安全性, 確保在這個演算法裡面沒有冗餘的方法和不可預測錯誤使用方式, 所以基於連結串列的這一系列的實現(包括上面的棧, 佇列, 以及揹包和RLU演算法)都是通過包裝連結串列已有的方法進行的實現, 同時這個協議的實現也提供了一種可能性, 就是如果有不同的想法, 比如我想用一個陣列來實現一個棧, 也可以通過這個協議指定的規範來統一實現相應的方法就行了. 同時需要說明的是,協議不代表你實現了這個協議就一定是實現了這樣的功能, 因為你可能實現了相同的方法但是邏輯並不是這麼回事, 所以協議僅僅只是一個規範, 遵守規範還是需要人為把控.

這裡要提一下就是要實現執行緒安全或者說是原子操作, 目前在iOS裡面有來之pthread的鎖(自旋鎖, 互斥鎖),以及GCD的訊號量, barrier,以及iOS10提出的unfair_lock等, 上面提到的都是比較典型的. 然後這裡要提醒一下的是自旋鎖和訊號量在iOS平臺都是不安全的方式.具體的大家可以搜尋一下很容易就能明白(不願意搜尋的我簡單提一下, 是由於優先順序的問題造成了無法unlock). 綜合很多資料比較效能之後選用的是互斥鎖, 並且選用了一個比較優的封裝方案(避免了閉包捕獲帶來的額外開銷, 以及swift對於inline的優化)

互斥鎖以及unfair_lock的封裝

相關文章