LRU、メモリ管理ページ置換アルゴリズムの一種ではなく、データ・ブロック(メモリブロック)用のメモリでは、LRU、データはLRUに基づいて、追加のデータをロードするためにスペースを作るために、メモリの外に移動属するオペレーティングシステムと呼ばれています
3つのキャッシュ使用ポリシーがあります。
- (先入れ先出し待ち行列で)FIFO
- LFU -頻度の最も低い(最低使用)に使用し
、最新の小さな数のデータの一部がアクセスされた場合は、将来的に数が非常に少ないアクセスすることが - LRU -最も最近(最低使用)に使用され
、最近では、データの一部がアクセスされていない場合、確率はアクセスされた後、非常に小さいです
スキーム:O(N)
単一順序付けられたリストを維持する。テールが最近使用され、ヘッドが使用する最初のものである。リストを横断するときに、新しいデータにアクセスすると、次のような状況
- リストにキャッシュされている場合は、このノードを取得、削除の末尾に移動
- キャッシュされない場合
- リストは、直接尾に、満杯でない場合
- リストがいっぱいになった場合は、新しいノードの頭と尾を削除
直接使用する場合は单链表
真、動作時間の複雑さはO(n)があるので、通常は別の手段があるだろう求める散列表
検索速度を向上させる。しかし、スペースはデータの完全であるとき、最初の使用を除去する必要があるので、それが配列の使用ことを確認する必要があります
オプションII:O(1)
整然としたハッシュテーブル:双方向のハッシュテーブルとリンクリストの実装では、ハッシュテーブルを迅速に検索するために使用され、データを格納するために使用される二重リンクリスト
実現
使用OrderDict達成
# coding:utf-8
from collections import OrderedDict
class LRUCache(object):
"""
借助OrderedDict的有序性实现, 内部使用了双向链表
"""
def __init__(self, max_length: int = 5):
self.max_length = max_length
self.o_dict = OrderedDict()
def get(self, key):
"""
如果找到的话移动到尾部
:param key:
:return:
"""
value = self.o_dict.get(key)
if value:
self.o_dict.move_to_end(key)
return value
def put(self, key, value):
if key in self.o_dict:
self.o_dict.move_to_end(key)
else:
if len(self.o_dict) >= self.max_length:
# 弹出最先插入的元素
self.o_dict.popitem(last=False)
self.o_dict[key] = value
if __name__ == "__main__":
lru = LRUCache(max_length=3)
lru.put(1, "a")
lru.put(2, "b")
lru.put(3, "c")
assert lru.o_dict == OrderedDict([(1, 'a'), (2, 'b'), (3, 'c')])
lru.get(2)
assert lru.o_dict == OrderedDict([(1, 'a'), (3, 'c'), (2, 'b')])
lru.put(4, "d")
assert lru.o_dict == OrderedDict([(3, 'c'), (2, 'b'), (4, "d")])
辞書やリスト実現を使用します
# coding:utf-8
from collections import deque
class LRUCache(object):
def __init__(self, max_length: int = 5):
self.max_length = max_length
self.cache = dict()
self.keys = deque()
def get(self, key):
if key in self.cache:
value = self.cache[key]
self.keys.remove(key)
self.keys.append(key)
else:
value = None
return value
def put(self, key, value):
if key in self.cache:
self.keys.remove(key)
self.keys.append(key)
else:
if len(self.keys) >= self.max_length:
self.keys.popleft()
self.keys.append(key)
else:
self.keys.append(key)
self.cache[key] = value
if __name__ == "__main__":
lru = LRUCache(max_length=3)
lru.put(1, "a")
lru.put(2, "b")
lru.put(3, "c")
assert lru.keys == deque([1, 2, 3])
lru.get(2)
assert lru.keys == deque([1, 3, 2])
lru.put(4, "d")
assert lru.keys == deque([3, 2, 4])
lru_cache
あなたが運ぶpython3.7キャッシュモジュールLRUで使用することができます
from functools import lru_cache
@lru_cache(maxsize=32)
def fibs(n: int):
if n == 0:
return 0
if n == 1:
return 1
return fibs(n-1) + fibs(n-2)
if __name__ == '__main__':
print(fibs(10))
アプリケーション
- LRUポリシーのRedis
- JavaののLinkedHashMap
ハッシュテーブルを使用し、二重リンクリストを実装
概要
- 配列はすぐに見つけるためにインデックスを使用しますが、欠点は、必要性、連続したメモリであります
- チェーン利点は、メモリが連続することはできませんが、遅い見つけることということです
- ハッシュ、リスト/ジャンプテーブルミックスは、配列とリンクリストの長所を組み合わせることです
データ
- 米国のデータ構造とアルゴリズム - 紛争の王