From 2a9239057eb0383d940daa19a3d7d264eca5776d Mon Sep 17 00:00:00 2001 From: YOGESH BHAKHAR <31646304+yogesh-mca17du@users.noreply.github.com> Date: Wed, 23 Oct 2019 12:13:23 +0530 Subject: [PATCH] Create LRU Cache Leetcode --- LRU Cache Leetcode | 249 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 LRU Cache Leetcode diff --git a/LRU Cache Leetcode b/LRU Cache Leetcode new file mode 100644 index 0000000..6137955 --- /dev/null +++ b/LRU Cache Leetcode @@ -0,0 +1,249 @@ +// Source : https://oj.leetcode.com/problems/lru-cache/ +/********************************************************************************** +* +* Design and implement a data structure for Least Recently Used (LRU) cache. +* It should support the following operations: get and set. +* +* get(key) - Get the value (will always be positive) of the key if the key exists +* in the cache, otherwise return -1. +* +* set(key, value) - Set or insert the value if the key is not already present. +* When the cache reached its capacity, it should invalidate +* the least recently used item before inserting a new item. +* +**********************************************************************************/ + +#include +#include +#include +#include +using namespace std; + +// The idea here is quite simple: +// 1) A Map to index the key. O(1) key search time-complexity. +// 2) A List to sort the cache data by accessed time. +// +// Considering there are too many insert/delete opreations for the List, +// The ouble linked list is the good data structure to performance it. + +class Node { + public: + int key; + int value; + Node *next, *prev; + Node(int k, int v) { key=k; value=v; next = prev = NULL; } + //Node(int k, int v, Node* n=NULL, Node* p=NULL): key(k), value(v), next(n), prev(p) {} +}; + +// the following double linked list seems a bit commplicated. +class DoubleLinkedList { + + private: + + Node *pHead, *pTail; + int size; + + + public: + + DoubleLinkedList(){ + pHead = pTail = NULL; + size = 0; + } + ~DoubleLinkedList() { + while(pHead!=NULL){ + Node*p = pHead; + pHead = pHead->next; + delete p; + } + } + + int Size() const { + return size; + } + + Node* NewAtBegin(int key, int value) { + Node *n = new Node(key, value); + return AddAtBegin(n); + } + + Node* NewAtEnd(int key, int value) { + Node *n = new Node(key, value); + return AddAtEnd(n); + } + + Node* AddAtBegin(Node* n){ + size++; + + if (pHead==NULL) { + pHead = pTail = n; + return n; + } + + n->next = pHead; + n->prev = NULL; + pHead->prev = n; + pHead = n; + return n; + } + + Node* AddAtEnd(Node* n) { + size++; + + if (pHead==NULL) { + pHead = pTail = n; + return n; + } + + pTail->next = n; + n->prev = pTail; + n->next = NULL; + pTail = n; + } + + void Unlink(Node* n){ + Node* before = n->prev; + Node* after = n->next; + + if (before){ + before->next = after; + } + + if (after){ + after->prev = before; + } + + if(pHead == n){ + pHead = pHead->next; + }else if(pTail == n) { + pTail = pTail->prev; + } + + size--; + } + + void Delete(Node* n){ + Unlink(n); + delete n; + } + + void TakeToBegin(Node* n){ + Unlink(n); + AddAtBegin(n); + } + + Node* GetTailNode() { + return pTail; + } + + void DeleteLast() { + Delete(pTail); + } + + void Print(){ + Node* p = pHead; + while(p!=NULL) { + cout << "(" << p->key << "," << p->value << ") "; + p = p->next; + } + cout << endl; + } +}; + + + +class LRUCache{ + + private: + //cacheList - store the date + DoubleLinkedList cacheList; + //cacheMap - index the date for searching + map cacheMap; + //the max capcity of cache + int capacity; + + public: + LRUCache(int capacity) { + this->capacity = capacity; + } + void print(){ + cacheList.Print(); + } + + int get(int key) { + // The accessed node must be up-to-time -- take to the front + if (cacheMap.find(key) != cacheMap.end() ){ + cacheList.TakeToBegin(cacheMap[key]); + return cacheMap[key]->value; + } + return -1; + + } + + void set(int key, int value) { + // key found, update the data, and take to the front + if (cacheMap.find(key) != cacheMap.end() ){ + Node *p = cacheMap[key]; + p->value = value; + cacheList.TakeToBegin(cacheMap[key]); + }else{ + // key not found, new a node to store data + cacheMap[key] = cacheList.NewAtBegin(key, value); + // if the capacity exceed, remove the last one. + if( cacheList.Size() > capacity) { + int key = cacheList.GetTailNode()->key; + cacheMap.erase(key); + cacheList.DeleteLast(); + } + } + } +}; + + +int main(int argc, char** argv) +{ + + /* + LRUCache c(2); + c.set(2,1); + c.print(); + c.set(2,2); + c.print(); + c.get(2); + c.print(); + c.set(1,1); + c.print(); + c.set(4,1); + c.print(); + c.get(2); + c.print(); + cout << "---------" << endl; + */ + srand(time(0)); + + int capacity = 5; + int test_loop_times = 10; + if (argc>1){ + capacity = atoi(argv[1]); + } + if (argc>2){ + test_loop_times = atoi(argv[1]); + } + + LRUCache cache(capacity); + + int v; + for(int i=0; i