日拱一卒 鍊錶 如何實現lru

2022-01-19 11:59:38 字數 2215 閱讀 4488

redis的記憶體淘汰機制好幾種,如ttl、random、lru。

lru(less recently used)即最近最少使用策略,表示在最近一段時間內最少被使用到的redis鍵,如果遇到記憶體不足,會有限淘汰這部分鍵來騰出更多空間。

今天就來說說lru這種淘汰策略是如何通過鍊錶這種結構實現的。

在鍊錶結構中,如何表示最近訪問的節點和如何表示最久沒有訪問的節點?

如何判定乙個鍊錶中是否存在要查詢的節點?

如何向鍊錶結構插入節點,並放在最近最新的節點位置?

如果在鍊錶中刪除乙個節點?

結合上面的難點,我們可以構建乙個可以解決問題的鍊錶模型。

如何表示最近訪問的節點和如何表示最久沒有訪問的節點

可以設計乙個雙向鍊錶,頭結點表示最近訪問的節點,尾結點表示最久沒有訪問的節點。使用雙向鍊錶是為了查詢和定位更加方便。

如何判定乙個鍊錶中是否存在要查詢的節點

解決這個問題,最直接的思路就是遍歷整個鍊錶,依次匹配如果找到相同的值,對應的節點就是待查詢的節點,如果遍歷完整個鍊錶,還是沒有找到,表示該鍊錶不存在該節點。

還有一種思路是將鍊錶的所有節點存放到乙個map結合中,查詢的時候直接通過map的key進行查詢即可。

如何向鍊錶結構插入節點,並放在最近最新的節點位置

結合前面幾篇,我們知道,鍊錶的插入和刪除是非常方便的,但是在lru問題背景下,如果插入節點並保證是最新的位置呢?顯然最新的節點是要放到頭結點的。

另外需要注意的點是,插入之前需要先查詢這個節點是否存在鍊錶中,如果存在需要先刪除。

如果在鍊錶中刪除乙個節點

刪除乙個節點的前置步驟應該是先判定乙個節點是否存在鍊錶中,如果存在刪除即可,如果不存在則無需刪除。

通過以上幾個問題,我們大概可以構想出幾個原子函式

下面我們主要看如何實現這幾個函式就可以了,主要**如下

初始化的雙向鍊錶如上圖所示,乙個節點包括資料部分data,前繼節點pre和後繼節點next。

所有節點資料放入map集合中。

get()方法會在map中查詢,如果不存在,則直接返回。如果存在,則呼叫remove先刪除該節點,再呼叫setheader將節點放入頭結點。

put()方法會首先在map中查詢對應節點,如果找到,則先呼叫remove刪除方法刪除改節點,並呼叫setheader方法將節點放入頭結點。

至此乙個lru的淘汰策略使用乙個雙向鍊錶就實現了。

前面幾篇,分別介紹了通過鍊錶結構如何實現鍊錶反轉、判斷鍊錶是否有環、鍊錶結構的回文判斷、有序鍊錶的合併以及本篇的lru實現。

鍊錶具備插入刪除方便,但是查詢效率較低的特性。

以下是對於鍊錶結構的梳理

日拱一卒(一)

layer list 用來多個圖層堆疊顯示的 在drawable資料夾下建立乙個xml檔案。比如 background.xml 另外在layout檔案中指定background屬性這樣就會載入pic1和pic2這兩張。imageview android background drawable bac...

日拱一卒(十四)

git 初識 1.安裝 linux sudo apt get install git core 2.建立 倉庫 linux下開啟shell,windows開啟git bash 1 配置下身份 git config global user.name tony git config global use...

日拱一卒(三十)

迪公尺特法則 lod 如果兩個類不能彼此直接通訊,那麼這兩個類就不應到發生直接的作用。如果其中乙個類需要呼叫另一類的某乙個方法的話,可以通過第三方 這個呼叫。白話 android中intent類就是這個很好的例項,activity,service之間設計就是這樣的松耦合,他們不直接通訊,而是用int...