算法描述

LRU实际上是设计一个数据结构,有如下要求:

  • 包含容量capacity和当前元素数量size
  • 包含插入方法put和获取get
  • 时间复杂度为O(1);

    算法设计

    一般来说通过两个数据结构来实现LRU机制,即

    • 哈希表:用于存取【鍵-节点】对
    • 双向链表:用于存取【键-值】对,尾节点为最新加入的节点,头节点的后一结点为LRU节点

    LRU缓存机制结构 - 图1

  1. struct Node{
  2. int key,value;
  3. Node *pre,*next;
  4. Node(int _k,int _v):
  5. key(_k),value(_v),pre(nullptr),next(nullptr){}
  6. };
  7. class LRUCache {
  8. const int MAXSIZE=3001;
  9. Node* head;
  10. Node* tail; /* for tail insertion method */
  11. vector<Node*> cache_;
  12. int capacity;
  13. int size;
  14. public:
  15. LRUCache(int c):
  16. size(0),capacity(c) {
  17. head=new Node(-1,-1);
  18. tail=head;
  19. cache_.resize(MAXSIZE,nullptr);
  20. }
  21. int get(int key) {
  22. if(cache_[key]==nullptr){
  23. /* not existed */
  24. return -1;
  25. }else{
  26. /* existed */
  27. Node* cur=cache_[key];
  28. /* if cur is tail, ignore update*/
  29. if(cur!=tail){
  30. /* release from original position */
  31. cur->pre->next=cur->next;
  32. cur->next->pre=cur->pre;
  33. /* update position to tail */
  34. tail->next=cur;
  35. cur->pre=tail;
  36. cur->next=nullptr;
  37. tail=cur;
  38. }
  39. return cur->value;
  40. }
  41. }
  42. void put(int key, int value) {
  43. if(get(key)==-1){
  44. /* existed */
  45. if(size<capacity){
  46. size++;
  47. }else{
  48. /* delete the head->next node */
  49. Node *popNode=head->next;
  50. if(popNode==tail){
  51. tail->next=nullptr;
  52. tail->pre=nullptr;
  53. head->next=nullptr;
  54. tail=head;
  55. }else{
  56. head->next=popNode->next;
  57. popNode->next->pre=head;
  58. }
  59. popNode->next=nullptr;
  60. popNode->pre=nullptr;
  61. /* important! remove it from cache */
  62. cache_[popNode->key]=nullptr;
  63. delete popNode;
  64. }
  65. /* create new node (tail insertion)*/
  66. Node *newNode=new Node(key,value);
  67. cache_[key]=newNode;
  68. tail->next=newNode;
  69. newNode->pre=tail;
  70. tail=newNode;
  71. }else{
  72. cache_[key]->value=value;
  73. }
  74. }
  75. };