当前位置:网站首页>布隆过滤器及LRU Cache的实现
布隆过滤器及LRU Cache的实现
2022-08-09 15:04:00 【凤求凰的博客】
一、Bloom Filter
它是什么?:一个很长的二进制向量和一系列随机映射函数
。
用途:布隆过滤器可以用于检索
、一个元素是否在一个集合
中。
优点:空间效率
和查询时间
都远远超过一般的算法,
缺点:有一定的误识别率
和删除困难
。
from bitarray import bitarray
import mmh3
class BloomFilter:
def __init__(self, size, hash_num):
self.size = size
self.hash_num = hash_num # 将一个数hash成几个二进制位?
self.bit_array = bitarray(size)
self.bit_array.setall(0)
def add(self, s):
for seed in range(self.hash_num):
res = mmh3.hash(s, seed) % self.size
self.bit_array[res] = 1
def look_up(self, s):
for seed in range(self.hash_num): # 得到三个二进制位
res = mmh3.hash(s, seed) % self.size # seed就是加的盐
if not self.bit_array[res]: # 有一位是0, 就是肯定不存在的
return "Nope"
return "Probably" # 所有位都存在, 也只是可能存在而已
二、LRU Cache
凰凰科普
- Cache缓存,LRU Cache就是采用
LRU算法实现的缓存
。- LRU算法,学过操作系统的同学相信应该对其不陌生,这是一种
内存淘汰策略
,当发生缺页中断
时, 需要从硬盘请求调页
到内存,如果内存满了,就需要淘汰一些内存页,淘汰那些页?LRU规定淘汰最近最久未使用的页!
两个要素:大小 、替换策略
实现:Hash Table
+ Double LinkedList
特点:
O(1) 查询
O(1) 修改、更新
1、OrderedDict实现
class LRUCache:
def __init__(self, capacity: int):
self.dic = collections.OrderedDict()
self.remain = capacity # size和cap是有区别的哈
def get(self, key: int) -> int:
if key not in self.dic:
return -1
v = self.dic.pop(key)
self.dic[key] = v
return v
def put(self, key: int, value: int) -> None:
if key in self.dic:
self.dic.pop(key)
else:
if not self.remain: # 维护cache的大小
self.dic.popitem(last = False)
self.remain += 1
self.remain -= 1
self.dic[key] = value
2、哈希 + 双向链表(面试建议)
class Node: # 定义双向链表的节点
def __init__(self, key = -1, val = -1):
self.key = key # 由于后面需要删除哈希表中的key,因此需要存下
self.val = val
self.next = None
self.prev = None
class LRUCache:
def __init__(self, capacity: int):
self.capacity = capacity
self.dic = dict()
# 定义一个伪头和伪尾,便于找头、找尾、头删、尾插
# 注意伪头这边才是最近最久未使用元素所在
self.head = Node()
self.tail = Node()
self.head.next = self.tail
self.tail.prev = self.head
# 查询元素,在哈希表中查,然后找到结点更新双向链表的尾元素
def get(self, key: int) -> int:
if key in self.dic:
v = self.dic[key]
self.__remove(v)
self.__add(v)
return v.val
return -1
# 插入元素,原来有就删除了,然后尾插,更新dic
# 如果超出容量,就删头,且在dic中删除对应的key
def put(self, key: int, value: int) -> None:
if key in self.dic:
self.__remove(self.dic[key])
tmp = Node(key, value)
self.dic[key] = tmp
self.__add(tmp)
if len(self.dic) > self.capacity:
tmp = self.tail.prev
self.__remove(tmp)
del self.dic[tmp.key]
def __remove(self, node):
p = node.prev
n = node.next
p.next = n
n.prev = p
def __add(self, node): # 添加肯定是在头部添加
tmp = self.head.next
self.head.next = node
node.next = tmp
tmp.prev = node
node.prev = self.head
边栏推荐
猜你喜欢
随机推荐
websocket协议详解
Win10 安装系统跳过创建用户,直接启用 administrator
Vim practical skills_3. Visual mode and command mode
Xshell显示乱码
List,Set,Map,Queue,Deque,Stack遍历方式总结
easywsclient的DEMO测试
unity3d画布/UI自适应屏幕的方式
数组指针的使用方法
webSocket的实现
Word 2016 撰写论文(1): 公式居中、编号右对齐
用指针和malloc定义一个数组
Fiddler抓包夜神模拟器
typescript学习(二)
uniapp封装全局js并在页面引用
传输层协议TCP/UDP
2022.7.16学习总结
JS字符串对象基础操作方法
VMware 虚拟机添加 2 张网卡 设置 NAT 与 桥接网络
weiteUP-ciscn_2019_c_1
客户端媒体引擎框架