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;
}

  

posted @   bonelee  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用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进制输出
点击右上角即可分享
微信分享提示