LRU cache实现,还是使用伪头部和伪尾部节点写代码更加简单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | class Node: def __init__( self , key, val): self .key = key self .val = val self .prev = None self . next = None class LRUCache: def __init__( self , capacity): self .capacity = capacity self .hashmap = {} # 使用伪头部和伪尾部节点 self .head = Node( 0 , 0 ) self .tail = Node( 0 , 0 ) self .head. next = self .tail self .tail.prev = self .head def get( self , key): if key in self .hashmap: node = self .hashmap[key] self ._remove(node) self ._add(node) return node.val return - 1 def put( self , key, value): if key in self .hashmap: self ._remove( self .hashmap[key]) node = Node(key, value) self ._add(node) self .hashmap[key] = node if len ( self .hashmap) > self .capacity: node = self .head. next self ._remove(node) del self .hashmap[node.key] def _remove( self , node): prev = node.prev next = node. next prev. next = next next .prev = prev def _add( self , node): prev = self .tail.prev prev. next = node self .tail.prev = node node.prev = prev node. next = self .tail # 创建一个容量为2的LRU缓存 cache = LRUCache( 2 ) # 插入键值对("192.168.1.1", 1) cache.put( "192.168.1.1" , 1 ) assert cache.get( "192.168.1.1" ) = = 1 # 返回1 # 插入键值对("192.168.1.2", 2) cache.put( "192.168.1.2" , 2 ) assert cache.get( "192.168.1.2" ) = = 2 # 返回2 # 再次访问键"192.168.1.1" assert cache.get( "192.168.1.1" ) = = 1 # 返回1 # 插入键值对("192.168.1.3", 3),这会导致键"192.168.1.2"被删除,因为它是最近最少使用的键 cache.put( "192.168.1.3" , 3 ) assert cache.get( "192.168.1.2" ) = = - 1 # 返回-1,因为键"192.168.1.2"已经被删除 # 再次访问键"192.168.1.1" assert cache.get( "192.168.1.1" ) = = 1 # 返回1 # 插入键值对("192.168.1.4", 4),这会导致键"192.168.1.3"被删除,因为它是最近最少使用的键 cache.put( "192.168.1.4" , 4 ) assert cache.get( "192.168.1.3" ) = = - 1 # 返回-1,因为键"192.168.1.3"已经被删除 |
核心:
(1)只要访问过,或者新节点,就将节点放到tail,区别无非是访问的节点修改前后link;
(2)只要是删除,就将节点从head里remove。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | void lru_add_to_tail( struct brief_asset_info *node) { // 将对应的节点添加到双向链表的尾部,作为LRU的最新节点 node->prev = g_asset_portray_lru.dummy_tail->prev; node->next = g_asset_portray_lru.dummy_tail; g_asset_portray_lru.dummy_tail->prev->next = node; g_asset_portray_lru.dummy_tail->prev = node; } void lru_move_to_tail( struct brief_asset_info *node) { // 移动节点到到双向链表的尾部,作为LRU的最新节点 node->prev->next = node->next; node->next->prev = node->prev; lru_add_to_tail(node); } struct brief_asset_info *lru_delete_head() { struct brief_asset_info *node = g_asset_portray_lru.dummy_head->next; g_asset_portray_lru.dummy_head->next = node->next; node->next->prev = g_asset_portray_lru.dummy_head; return node; } |
实际C代码应用伪代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | struct asset_nlog_ua *asset_check_iot_xxx( struct asset_info *info, bool *is_counterfeit) { struct ip_mac ip_mac_key = {0}; ip_mac_key.ip = info->ip; ip_mac_key.mac = info->mac; struct ase_hash *asset_portray = g_asset_portray_lru.asset_portray_map; struct brief_asset_info *found_info = asset_find_iot_portray(&ip_mac_key, asset_portray); struct asset_nlog_ua *event = NULL; if (found_info != NULL) { if (check_asset_conflict(found_info, info)) { // 误报检查,非误报才生成事件 if (!asset_check_counterfeit_false_alarm(&found_info->ip_mac_key.ip, &found_info->ip_mac_key.mac)) { *is_counterfeit = true ; event = asset_generate_iot_event(found_info, info); // 刷新LRU cache,更新访问的最新资产 lru_move_to_tail(found_info); return ; } } // 资产属性不冲突,或者冲突但属于误报,更新已经存在的画像 asset_update_iot_portray(info, found_info, asset_portray); // 刷新LRU cache,更新修改后的最新资产 lru_move_to_tail(found_info); } else { // 新建画像,需要考虑是否满规格,满规格情况下需要删除LRU中的老资产 if (g_asset_portray_lru.asset_portray_map->n_entry >= g_asset_portray_lru.capacity) { ASE_INFO(ASE_CATE_ASSET, "[iot] asset_portray_map exceed max capacity, will asset_delete_oldest_portray." ); asset_delete_oldest_portray(asset_portray); } struct brief_asset_info *new_info = asset_insert_iot_portray(info, asset_portray); // 刷新LRU cache,更新新建的最新资产 lru_add_to_tail(new_info); } return event; } |
标签:
算法
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
2021-01-11 判断回文串——相向双指针
2019-01-11 需要排序的最短子数组的长度——是一个排序好的数组,中间某一部分被打乱了,让你找出打乱的那个子数组
2018-01-11 利用Powershell和ceye.io实现Windows账户密码回传
2018-01-11 Local Response Normalization作用——对局部神经元的活动创建竞争机制,使得其中响应比较大的值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力
2018-01-11 python 读取二进制文件 转为16进制输出