题目: 运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。
获取数据 get(key) - 如果关键字 (key) 存在于缓存中,则获取关键字的值(总是正数),否则返回 -1。 写入数据 put(key, value) - 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字/值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。
原题链接
解题思路: 采用双向链表和哈希表实现。双向链表中记录key, val两个值,以及prev和next两个指针。哈希表以key作为索引,值为链表节点。
获取数据时,在哈希表中根据key查找
key在哈希表中,根据表中存储的链表节点返回val;并将该节点放到链表的头部。
key不在哈希表中,返回-1。
写入数据时,判断key是否已经在哈希表中
key在哈希表中,重新覆盖该链表的val值,并将该链表节点移动至头部;
key不在哈希表中,新建一个链表节点,并将链表节点放到头部;之后判断此时的链表长度是否超过容量,若超过容量,则删除链表的尾部节点,并将该节点对应的key从哈希表中删除。
代码:
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 74 75 76 77 78 79 80 81 82 83 84 85 86 87 struct dListNode { int key; int val; dListNode* prev; dListNode* next; dListNode (): key (0 ), val (0 ), prev (NULL ), next (NULL ){} dListNode (int k, int v): key (k), val (v), prev (NULL ), next (NULL ) {} }; class LRUCache {private : int size; int capacity; dListNode* head = new dListNode (); dListNode* tail = new dListNode (); unordered_map<int , dListNode*> cache; public : LRUCache (int capacity) { this ->capacity = capacity; this ->size = 0 ; this ->head->next = this ->tail; this ->tail->prev = this ->head; } int get (int key) { if (!cache.count (key)) { return -1 ; } else { dListNode* tmp = cache[key]; mv2head (tmp); return tmp->val; } } void put (int key, int value) { if (!cache.count (key)) { dListNode* tmp = new dListNode (key, value); cache[key] = tmp; add2head (tmp); size += 1 ; if (size>capacity) { dListNode* tail_rmed = rm_tail (); cache.erase (tail_rmed->key); delete tail_rmed; size -= 1 ; } } else { dListNode* tmp = cache[key]; tmp->val = value; mv2head (tmp); } } void rm_node (dListNode* p) { p->next->prev = p->prev; p->prev->next = p->next; } void add2head (dListNode* p) { p->next = head->next; p->prev = head; head->next = p; p->next->prev = p; } dListNode* rm_tail () { dListNode* tmp = tail->prev; tail->prev = tmp->prev; tail->prev->next = tail; return tmp; } void mv2head (dListNode* p) { rm_node (p); add2head (p); } ~LRUCache () { while (head) { dListNode* tmp = head->next; delete head; head = tmp; } } };