《iOS面試題整理》- LRU 算法

數(shù)組實現(xiàn)

 var cache: [Int] = []
let maxCount = 5 // 緩存最大值

extension Array where Element: Equatable {
    mutating func remove(_ object: Element) {
        if let index = index(of: object) {
            remove(at: index)
        }
    }
}

func LRU (data : Int){
    // 如果沒有緩存
    if !cache.contains(data) {
        // 數(shù)組滿了, 移除最后一個數(shù)據(jù)
        if cache.count == maxCount { cache.removeLast() }
    } else {
        cache.remove(data)
    }
    cache.insert(data, at: 0)
}

LRU(data: 1)
LRU(data: 2)
LRU(data: 3)
LRU(data: 4)
LRU(data: 5)

print(cache)

// 數(shù)組滿了
LRU(data: 6)
print(cache)

// 相同元素
LRU(data: 4)
print(cache)

輸出
[5, 4, 3, 2, 1]
[6, 5, 4, 3, 2]
[4, 6, 5, 3, 2]

鏈表實現(xiàn)

  class ListNode<T> {
    var value: T
    var previous: ListNode?
    var next : ListNode?
    init(_ value: T) {
        self.value = value
    }
}

class List<T> {
    typealias Node = ListNode<T>
    
    private var head: Node?
    private var tail: Node?
    
    // 判斷是否為空
    var isEmpty: Bool { return head == nil }
    
    // 獲取頭節(jié)點
    var first: Node? { return head }
    
    // 獲取尾節(jié)點
    var last : Node? { return tail }
    
    // 鏈表數(shù)量
    var count: Int = 0;
    
    // 下標(biāo)
    subscript(index: Int) -> T? {
        var i = index
        var next = head
        while i > 0 {
            i -= 1
            next = next?.next
        }
        return next?.value
    }
    
    // 插入尾部
    func insert(value : T) {
        
        let newNode = Node(value)
        
        if let first = head {
            newNode.next = first
            first.previous = newNode
            head = newNode;
        } else {
            head = newNode
            tail = newNode
        }
        count += 1
    }
    
    // 移除某個節(jié)點
    func remove(node: Node) {
        
        let pre = node.previous
        let next = node.next
        
        pre?.next = next
        next?.previous = pre
        
        if pre == nil { head = node.next }
        if tail == nil { tail = node.previous }
        
        count -= 1
    }
    
    // 移除最后一個節(jié)點
    func removeLast() {
        remove(node: last!)
    }
    
    // 移動某個節(jié)點到頭部
    func moveToHead(node: Node) {
        
        let pre = node.previous
        let next = node.next
        
        pre?.next = next
        next?.previous = pre
        
        node.next = head
        head?.previous = node
        
        head = node
        
        if pre == nil { return }
        if next == nil  { tail = pre}
    }
}

class CacheLRU<T> {
    var limit : Int
    var cache : List<T>
    init(cacheCount: Int) {
        self.limit = cacheCount
        self.cache = List<T>()
    }
    
    // 添加數(shù)據(jù)
    func add(value: T) {
        if cache.count == limit { cache.removeLast()}
        cache.insert(value:value)
    }
    
    // 移動數(shù)據(jù)
    func move(value: ListNode<T>) {
        cache.moveToHead(node: value)
    }
}

extension List where T == Dictionary<String, String> {
    // 判斷鏈表是否含有緩存
    func contains(name: String) -> Node? {
        var next = head
        var index = 0
        while index < count {
            if next?.value[name] != nil { return next }
            index += 1
            next = next?.next
        }
        return nil;
    }
    
    // 打印 log 信息
    func log() {
        var next = head
        while next != nil {
            print(next?.value as Any)
            next = next?.next
        }
    }
}

extension CacheLRU where T == Dictionary<String, String> {
    
    // 訪問已有的數(shù)據(jù)
    func fetch(key : String) {
        let node = cache.contains(name: key)
        if let dic = node?.value {
            // 存在的話, 直接取數(shù)據(jù)
            print(dic)
            
            // 移動到頭節(jié)點
            move(value: node!)
        } else {
            
        }
    }
}

let cacheManager = CacheLRU<Dictionary<String, String>>(cacheCount: 2)
let value1 = ["1" : "測試1"]
let value2 = ["2" : "測試2"]
let value3 = ["3" : "測試3"]

// 模擬添加數(shù)據(jù)
cacheManager.add(value: value1)
cacheManager.add(value: value2)
cacheManager.add(value: value3)
cacheManager.cache.log()

// 模擬訪問數(shù)據(jù)
cacheManager.fetch(key: "2")
cacheManager.cache.log()


輸出
添加數(shù)據(jù)
Optional(["3": "測試3"])
Optional(["2": "測試2"])
訪問數(shù)據(jù)
["2": "測試2"]
Optional(["2": "測試2"])
Optional(["3": "測試3"])
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末腿倚,一起剝皮案震驚了整個濱河市都弹,隨后出現(xiàn)的幾起案子瞳腌,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蚀同,死亡現(xiàn)場離奇詭異卧抗,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)底燎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門刃榨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人双仍,你說我怎么就攤上這事枢希。” “怎么了朱沃?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵苞轿,是天一觀的道長。 經(jīng)常有香客問我逗物,道長搬卒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任翎卓,我火速辦了婚禮契邀,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘失暴。我一直安慰自己坯门,他們只是感情好微饥,可當(dāng)我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著古戴,像睡著了一般欠橘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上允瞧,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天简软,我揣著相機(jī)與錄音,去河邊找鬼述暂。 笑死痹升,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的畦韭。 我是一名探鬼主播疼蛾,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼艺配!你這毒婦竟也來了察郁?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤转唉,失蹤者是張志新(化名)和其女友劉穎皮钠,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體赠法,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡麦轰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了砖织。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片款侵。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖侧纯,靈堂內(nèi)的尸體忽然破棺而出新锈,到底是詐尸還是另有隱情,我是刑警寧澤眶熬,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布妹笆,位于F島的核電站,受9級特大地震影響娜氏,放射性物質(zhì)發(fā)生泄漏晾浴。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一牍白、第九天 我趴在偏房一處隱蔽的房頂上張望脊凰。 院中可真熱鬧,春花似錦、人聲如沸狸涌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽帕胆。三九已至朝捆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間懒豹,已是汗流浹背芙盘。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留脸秽,地道東北人儒老。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像记餐,于是被迫代替她去往敵國和親驮樊。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內(nèi)容