面試再也不怕,20行Python代碼幫你搞懂LRU算法

LRU算法在後端工程師面試中,是一個比較常出現的題目,這篇文章帶你們一塊兒,理解LRU算法,並最終用Python輕鬆實現一個基於LRU算法的緩存。python

緩存是什麼

先看一張圖,當咱們訪問網頁,瀏覽器會給服務器發請求,服務器會通過一系列的運算,把頁面返回給瀏覽器。面試

當有多個瀏覽器同時訪問的時候,就會在短期內發起多個請求,而服務器對每個請求都要進行一系列相同的操做。重複工做不只浪費資源,還可能致使響應速度變慢。算法

而緩存則能夠把服務器返回的頁面保存下來,當有其餘的瀏覽器再訪問時候,就沒必要勞服務器大駕,直接由緩存返回頁面。爲了保證響應速度,緩存一般是基於比較昂貴的硬件,好比RAM,這就決定了咱們很難用大量的緩存把全部的頁面都存下來,當剛好沒有緩存瀏覽器請求的頁面時,依然須要請求服務器。因爲緩存容量有限,而數據量無限(互聯網天天新產生的頁面數沒法估計),就須要把好剛用在刀刃上,緩存那些最有用的信息。後端

LRU是什麼

LRU是一種緩存淘汰算法(在OS中也叫內存換頁算法),因爲緩存空間是有限的,因此要淘汰緩存中不經常使用的數據,留下經常使用的數據,達到緩存效率的最大化。LRU就是這樣一種決定「淘汰誰留下誰」的算法,LRU是Least recently used的縮寫,從字面意思「最近最少使用」,咱們就能夠理解LRU的淘汰規則。瀏覽器

LRU的淘汰邏輯

咱們用一張圖來描述LRU的淘汰邏輯,圖中的緩存是一個列表結構,上面是頭結點下面是尾節點,緩存容量爲8(8個小格子):緩存

  • 有新數據(意味着數據以前沒有被緩存過)時,加入到列表頭
  • 緩存到達最大容量時,須要淘汰數據多出來的數據,此時淘汰列表尾部的數據
  • 當緩存中有數據被命中,則將數據移動到列表頭部(至關於新加入緩存)

按上面的邏輯咱們能夠看到,一個數據若是常常被訪問就會不斷地被移動到列表頭部,不會被淘汰出緩存,而越不常常訪問的數據,越容易被擠出緩存。服務器

20行Python代碼實踐LRU

接下來咱們用Python來實現一個採用LRU算法的緩存。數據結構

從前面的文章中咱們能夠知道,緩存簡化下來就兩個功能,一個是往裏裝數據(緩存數據),一個是往外吐數據(命中緩存),因此咱們的緩存對外只須要put和get兩個接口就能夠了。性能

按照前面的示意圖,緩存內部咱們只須要有一個列表(list)就能夠實現LRU邏輯,不過用列表雖然能實現邏輯,可是在判斷是否命中緩存時,速度可能很是慢(列表須要遍歷才能知道數據有沒有在裏面)。在Python中,咱們能夠用基於hash的結構,好比字典(dict)或集合(set),來快速判斷數據是否存在,解決列表實現的性能問題。可是字典和集合又是沒有順序的,若是能有一種既能排序,又是基於hash存儲的數據結構,就行了。spa

在Python的collections包中,已經內置了這種實用的結構OrderedDict,OrderedDict是dict的子類,可是存儲在內部的元素是有序的(列表的特色)。

解決了數據結構的問題,咱們能夠直接上手寫邏輯了,代碼以下:

class LRUCache:

    def __init__(self, capacity):
        self.capacity = capacity
        self.queue = collections.OrderedDict()
    
    def get(self, key):
        if key not in self.queue:
            return -1 // 要找的數據不在緩存中返回-1
        value = self.queue.pop(key) // 將命中緩存的數據移除
        self.queue[key] = value // 將命中緩存的數據從新添加到頭部
        return self.queue[key]
        

    def put(self, key, value):
        if key in self.queue: // 若是已經在緩存中,則先移除老的數據
            self.queue.pop(key)
        elif len(self.queue.items()) == self.capacity:
            self.queue.popitem(last=False) // 若是不在緩存中而且到達最大容量,則把最後的數據淘汰
        self.queue[key] = value // 將新數據添加到頭部
複製代碼

下次面試在遇到LRU的題目,是否是就成竹在胸了?

掃碼關注Python私房菜

Python實踐原創內容
相關文章
相關標籤/搜索