python基于雙向鏈表實現LFU算法
本文實例為大家分享了python實現LFU算法的具體代碼,供大家參考,具體內容如下
在第一節(jié)中實現了雙向鏈表DoubleLinkedList類,上一節(jié)中基于雙向鏈表實現了LRU算法,本節(jié)課我們繼續(xù)基于雙向鏈表實現LFU(Least frequently used 最不經常使用)算法。
一、重寫Node節(jié)點類
構建LFUNode類 繼承自第一節(jié)中的Node類,添加freq屬性用來表示節(jié)點使用頻率
class LFUNode(Node): ? ? def __init__(self, key, value): ? ? ? ? """ ? ? ? ? LFU節(jié)點 增加頻率屬性 ? ? ? ? :param key: ? ? ? ? :param value: ? ? ? ? """ ? ? ? ? self.freq = 0 ? ? ? ? super(LFUNode, self).__init__(key, value)
二、LFU實現
LFU的實現除了get和put之外還有一個私有的__update_freq更新節(jié)點頻率方法,讀寫某節(jié)點時都需要對該節(jié)點的頻率屬性進行更新。除了map之外新增加一個freq_map來存儲每個頻率下的雙向鏈表,當達到最大容量時移除最小頻率下的頭部的節(jié)點。
class LFUCache(object): ? ? def __init__(self, capacity=0xffffffff): ? ? ? ? """ ? ? ? ? LFU緩存置換算法 最不經常使用 ? ? ? ? :param capacity: ? ? ? ? """ ? ? ? ? self.capacity = capacity ? ? ? ? self.size = 0 ? ? ? ? self.map = {} ? ? ? ? self.freq_map = {} ? ? def __update_freq(self, node): ? ? ? ? """ ? ? ? ? 更新節(jié)點頻率 ? ? ? ? :param node: ? ? ? ? :return: ? ? ? ? """ ? ? ? ? freq = node.freq ? ? ? ? # 當前節(jié)點所在頻率存在 在當前頻率鏈表中移除當前節(jié)點 ? ? ? ? if freq in self.freq_map: ? ? ? ? ? ? node = self.freq_map[freq].remove(node) ? ? ? ? ? ? # 當前頻率鏈表為空時刪除該頻率鏈表 ? ? ? ? ? ? if self.freq_map[freq].size == 0: ? ? ? ? ? ? ? ? del self.freq_map[freq] ? ? ? ? # 將節(jié)點按照新頻率寫入頻率鏈表 ? ? ? ? freq += 1 ? ? ? ? node.freq = freq ? ? ? ? if freq not in self.freq_map: ? ? ? ? ? ? self.freq_map[freq] = DoubleLinkedList() ? ? ? ? self.freq_map[freq].append(node) ? ? ? ? return node ? ? def get(self, key): ? ? ? ? """ ? ? ? ? 獲取元素 ? ? ? ? :return: ? ? ? ? """ ? ? ? ? # 節(jié)點不存在 ? ? ? ? if key not in self.map: ? ? ? ? ? ? return None ? ? ? ? # 節(jié)點存在 更新使用頻率 ? ? ? ? old_node = self.map.get(key) ? ? ? ? new_node = self.__update_freq(old_node) ? ? ? ? self.map[key] = new_node ? ? ? ? return new_node.value ? ? def put(self, key, value): ? ? ? ? """ ? ? ? ? 設置元素 ? ? ? ? :param key: ? ? ? ? :param value: ? ? ? ? :return: ? ? ? ? """ ? ? ? ? # 節(jié)點已存在 更新頻率 ? ? ? ? if key in self.map: ? ? ? ? ? ? old_node = self.map.get(key) ? ? ? ? ? ? old_node.value = value ? ? ? ? ? ? new_node = self.__update_freq(old_node) ? ? ? ? ? ? self.map[key] = new_node ? ? ? ? else: ? ? ? ? ? ? # 節(jié)點容量達到上限 移除最小頻率鏈表頭部的節(jié)點 ? ? ? ? ? ? if self.size >= self.capacity: ? ? ? ? ? ? ? ? min_freq = min(self.freq_map) ? ? ? ? ? ? ? ? node = self.freq_map[min_freq].pop() ? ? ? ? ? ? ? ? del self.map[node.key] ? ? ? ? ? ? ? ? self.size -= 1 ? ? ? ? ? ? # 構建新的節(jié)點 更新頻率 ? ? ? ? ? ? new_node = LFUNode(key, value) ? ? ? ? ? ? new_node = self.__update_freq(new_node) ? ? ? ? ? ? self.map[key] = new_node ? ? ? ? ? ? self.size += 1 ? ? ? ? return new_node ? ? def print(self): ? ? ? ? """ ? ? ? ? 打印當前鏈表 ? ? ? ? :return: ? ? ? ? """ ? ? ? ? for freq, link in self.freq_map.items(): ? ? ? ? ? ? print("frequencies: %d" % freq) ? ? ? ? ? ? link.print()
三、測試邏輯
if __name__ == '__main__': ? ? lfu_cache = LFUCache(4) ? ? lfu_cache.put(1, 1) ? ? lfu_cache.print() ? ? lfu_cache.put(2, 2) ? ? lfu_cache.print() ? ? print(lfu_cache.get(1)) ? ? lfu_cache.print() ? ? lfu_cache.put(3, 3) ? ? lfu_cache.print() ? ? lfu_cache.put(4, 4) ? ? lfu_cache.print() ? ? lfu_cache.put(5, 5) ? ? lfu_cache.print() ? ? print(lfu_cache.get(2)) ? ? lfu_cache.put(4, 400) ? ? lfu_cache.print()
測試結果:
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
pip 錯誤unused-command-line-argument-hard-error-in-future解決辦法
這篇文章主要介紹了Python包管理器pip安裝軟件時出現unused-command-line-argument-hard-error-in-future錯誤的解決辦法,需要的朋友可以參考下2014-06-06Python的matplotlib繪圖如何修改背景顏色的實現
這篇文章主要介紹了Python的matplotlib繪圖如何修改背景顏色的實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-07-07安裝pycurl報錯Could not run curl-config: &ap
這篇文章主要為大家介紹了安裝pycurl報錯Could not run curl-config: 'curl-config'解決方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-12-12pycharm遠程連接服務器調試tensorflow無法加載問題
最近打算在win系統下使用pycharm開發(fā)程序,并遠程連接服務器調試程序,其中在import tensorflow時報錯,本文就來介紹一下如何解決,感興趣的可以了解一下2021-06-06django為Form生成的label標簽添加class方式
這篇文章主要介紹了django為Form生成的label標簽添加class方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-05-05