來源1:http://blog.csdn.net/tinyway/article/details/24536327html
來源2:https://www.cnblogs.com/mushroom/p/4278275.html#o1node
來源3:雙向列表的插入順序: https://www.cnblogs.com/Renyi-Fan/p/7512789.html數組
LRU便是:把最近最少訪問的數據給淘汰掉,常常被訪問到便是熱點數據。數據結構
關於LRU數據結構:由於key優先級提高和key淘汰,因此須要順序結構。函數
新數據插入到鏈表頭部、被命中時的數據移動到頭部,添加複雜度O(1),移動和獲取複雜度O(N)。spa
LRU的實現有這樣幾種思路:.net
一、利用數組保存節點信息,另外節點信息除了內容還須要保存最近使用狀況。code
缺點:每次都須要遍從來找信息,同時也要遍從來刪除(指LRU cache滿了的狀況)htm
二、鏈表來保存節點,雙向鏈表,最末端爲最新使用的,這樣能減小刪除時候的時間效率。blog
三、還能夠用一個哈希表來儲存key值對應的節點的地址,這樣就能夠實現查找O(1),刪除添加O(1)了
//用雙向鏈表來做爲LRU的結構 //其中表頭表示早入表的節點,表尾表示最新的節點 struct ListNode{ string key; string value; ListNode* next; ListNode* pre; //struct的構造函數 ListNode(string k,string v):key(k),value(v),next(NULL),pre(NULL){} }; class LRUCache{ private: int cap; int nodeNum; ListNode pHead; ListNode PTail; public: LRUCache(int capacity):cap(capacity),nodeNum(0),pHead(NULL),pTail(NULL){} string get(string key){ if(pHead==NULL) return ''; ListNode *pNode = pHead; while(pNode != NULL){ if(pNode->key == key){ string val = pNode->value; DeleteFromList(pNode); AddToList(pNode); return val } pNode = pNode->next; } //key is not found return '' } void set(string key, string val){ ListNode pNode = pHead; //要考慮爲已有的key從新賦值 while(pNode!=NULL){ if(pNode->key==key){ pNode->value = val; DeleteFromList(pNode); AddToList(pNode); return; } pNode = pNode->next; } //爲一個新的key存值 pNode = new ListNode(key,val); AddToList(pNode); } //刪除pNode void DeleteFromList(ListNode* pNode){ ListNode* pPre = pNode->pre; ListNode* pNext = pNode->next; nodeNum--; //將pPre的next指向pNext即刪除,但要考慮pNode是鏈表頭的狀況 if(pPre==NULL) pHead=pNext; else pPre->next = pNext; //將pNext的pre指向pPre即刪除,但要考慮pNode是鏈表尾的狀況 if(pNext==NULL) pTail = pPre; else pNext->pre = pPre; } //將pNode添加到鏈表 void AddToList(ListNode* pNode){ if(nodeNum == cap){ ListNode* pTmp = pHead; pHead = pHead->next; DeleteFromList(pTmp); delete pTmp; AddToList(pNode); } else{ ++nodeNum; if(nodeNum == 1){ pHead = pNode; pTail = PNode; } else{ //對於尾端加鏈表,不單單是鏈表插入順序,還要更新pTail pNode->pre = pTail; pNode->next = pTail->next; pTail->next = pNode; pTail = pNode; } } } } //雙向鏈表維護:pHead,pTail,numNode這三個成員,平時的操做要注意numNode //邊界狀況必定要注意維護pHead和pTail。
基於map或是dict的待完成。