Algorithm(一)LRU-cache
阿新 • • 發佈:2019-04-29
Leetcode-264
from collections import OrderedDict class LRUCache(object): def __init__(self, capacity): self.capacity = capacity self.cache = OrderedDict() def get(self, key): if key not in self.cache: return -1 value = self.cache[key] self.cache.pop(key) self.cache[key] = value return value def put(self, key, value): if key in self.cache: self.cache.pop(key) self.cache[key] = value else: if len(self.cache.keys()) == self.capacity: self.cache.popitem(last=False) self.cache[key] = value
/************************************************************************/ /* 單鏈表版本 /************************************************************************/ struct Node { int m_nKey; int m_nValue; Node* m_pNext; }; class LRUCache { public: LRUCache(int capacity) { m_nSize = capacity; m_nCount = 0; m_lruList = NULL; } int get(int key) { if (NULL == m_lruList) return -1; map<int, Node *>::iterator it = m_lruMap.find(key); if (it == m_lruMap.end()) //沒有找到 return -1; else { Node *p = it->second; //把節點移到連結串列的開頭 pushFront(p); } return m_lruList->m_nValue; } void set(int key, int value) { if (NULL == m_lruList) { m_lruList = new Node(); m_lruList->m_nKey = key; m_lruList->m_nValue = value; m_lruList->m_pNext = NULL; m_nCount ++; m_lruMap[key] = m_lruList; } else { map<int, Node *>::iterator it = m_lruMap.find(key); if (it == m_lruMap.end()){ //沒有命中,將連結串列的最後一個節點刪除 if (m_nSize == m_nCount) { //cache已滿 Node *pHead = m_lruList; Node *pTemp = pHead; while(pHead->m_pNext != NULL) { pTemp = pHead; pHead = pHead->m_pNext; } m_lruMap.erase(pHead->m_nKey); m_nCount --; if (pHead == pTemp) //只有一個節點 pHead = NULL; else pTemp->m_pNext = NULL; } Node *p = new Node(); //插入新的節點於頭部 p->m_nKey = key; p->m_nValue = value; p->m_pNext = m_lruList; m_lruList = p; m_lruMap[key] = m_lruList; m_nCount ++; } else { //命中,則將該命中的節點移至連結串列頭部 Node *pCur = it->second; pCur->m_nValue = value; pushFront(pCur); } } } void pushFront(Node *pCur) { //把節點移動到連結串列頭部,時間複雜度O(n) if (NULL == pCur) return; if (m_nCount == 1 || pCur == m_lruList) return; Node *pHead = m_lruList; while (pHead->m_pNext != pCur) pHead = pHead->m_pNext; pHead->m_pNext = pCur->m_pNext; pCur->m_pNext = m_lruList; m_lruList = pCur; } void printCache() { Node *p = m_lruList; while (p) { cout << p->m_nKey << ":" << p->m_nValue << " "; p = p->m_pNext; } } private: int m_nSize; int m_nCount; map<int, Node *> m_lruMap; Node* m_lruList; };
/************************************************************************/ /* 雙鏈表版本 /************************************************************************/ struct Node { int m_nKey; int m_nValue; Node* m_pNext; Node* m_pPre; }; class LRUCache { public: LRUCache(int capacity) { m_nSize = capacity; m_nCount = 0; m_lruListHead = NULL; m_lruListTail = NULL; } int get(int key) { if (NULL == m_lruListHead) return -1; map<int, Node *>::iterator it = m_lruMap.find(key); if (it == m_lruMap.end()) //沒有找到 return -1; else { Node *p = it->second; //把節點移到連結串列的開頭 pushFront(p); } return m_lruListHead->m_nValue; } void set(int key, int value) { if (NULL == m_lruListHead) { m_lruListHead = new Node(); m_lruListHead->m_nKey = key; m_lruListHead->m_nValue = value; m_lruListHead->m_pNext = NULL; m_lruListHead->m_pPre = NULL; m_lruListTail = m_lruListHead; m_nCount ++; m_lruMap[key] = m_lruListHead; } else { map<int, Node *>::iterator it = m_lruMap.find(key); if (it == m_lruMap.end()){ //沒有命中,將連結串列的最後一個節點刪除 if (m_nSize == m_nCount) { //cache已滿 if (m_lruListHead == m_lruListTail) {//只有一個節點 m_lruMap.erase(m_lruListHead->m_nKey); m_lruListHead->m_nKey = key; m_lruListHead->m_nValue = value; m_lruMap[key] = m_lruListHead; } else { Node *p = m_lruListTail; m_lruListTail->m_pPre->m_pNext = NULL; m_lruListTail = m_lruListTail->m_pPre; m_lruMap.erase(p->m_nKey); p->m_nKey = key; p->m_nValue = value; p->m_pNext = m_lruListHead; p->m_pPre = NULL; m_lruListHead->m_pPre = p; m_lruListHead = p; m_lruMap[key] = m_lruListHead; } } else { Node *p = new Node(); //插入新的節點於頭部 p->m_nKey = key; p->m_nValue = value; p->m_pNext = m_lruListHead; p->m_pPre = NULL; m_lruListHead->m_pPre = p; m_lruListHead = p; m_lruMap[key] = m_lruListHead; m_nCount ++; } } else { //命中,則將該命中的節點移至連結串列頭部 Node *pCur = it->second; pCur->m_nValue = value; pushFront(pCur); } } } void pushFront(Node *pCur) { //把節點移動到連結串列頭部,時間複雜度O(1) if (NULL == pCur) return; if (m_nCount == 1 || pCur == m_lruListHead) return; if (pCur == m_lruListTail) { //假如是尾節點 pCur->m_pPre->m_pNext = NULL; pCur->m_pNext = m_lruListHead; m_lruListTail = pCur->m_pPre; m_lruListHead->m_pPre = pCur; m_lruListHead = pCur; } else { pCur->m_pPre->m_pNext = pCur->m_pNext; pCur->m_pNext->m_pPre = pCur->m_pPre; pCur->m_pNext = m_lruListHead; m_lruListHead->m_pPre = pCur; m_lruListHead = pCur; } } void printCache() { Node *p = m_lruListHead; while (p) { cout << p->m_nKey << ":" << p->m_nValue << " "; p = p->m_pNext; } } private: int m_nSize; int m_nCount; map<int, Node *> m_lruMap; Node* m_lruListHead; Node* m_lruListTail; };
STL
#include <iostream>
#include <hash_map>
#include <list>
#include <utility>
using namespace std;
using namespace stdext;
class LRUCache{
public:
LRUCache(int capacity) {
m_capacity = capacity ;
}
int get(int key) {
int retValue = -1 ;
hash_map<int, list<pair<int, int> > :: iterator> ::iterator it = cachesMap.find(key) ;
//如果在Cashe中,將記錄移動到連結串列的最前端
if (it != cachesMap.end())
{
retValue = it ->second->second ;
//移動到最前端
list<pair<int, int> > :: iterator ptrPair = it -> second ;
pair<int, int> tmpPair = *ptrPair ;
caches.erase(ptrPair) ;
caches.push_front(tmpPair) ;
//修改map中的值
cachesMap[key] = caches.begin() ;
}
return retValue ;
}
void set(int key, int value) {
hash_map<int, list<pair<int, int> > :: iterator> ::iterator it = cachesMap.find(key) ;
if (it != cachesMap.end()) //已經存在其中
{
list<pair<int, int> > :: iterator ptrPait = it ->second ;
ptrPait->second = value ;
//移動到最前面
pair<int , int > tmpPair = *ptrPait ;
caches.erase(ptrPait) ;
caches.push_front(tmpPair) ;
//更新map
cachesMap[key] = caches.begin() ;
}
else //不存在其中
{
pair<int , int > tmpPair = make_pair(key, value) ;
if (m_capacity == caches.size()) //已經滿
{
int delKey = caches.back().first ;
caches.pop_back() ; //刪除最後一個
//刪除在map中的相應項
hash_map<int, list<pair<int, int> > :: iterator> ::iterator delIt = cachesMap.find(delKey) ;
cachesMap.erase(delIt) ;
}
caches.push_front(tmpPair) ;
cachesMap[key] = caches.begin() ; //更新map
}
}
private:
int m_capacity ; //cashe的大小
list<pair<int, int> > caches ; //用一個雙鏈表儲存cashe的內容
hash_map< int, list<pair<int, int> > :: iterator> cachesMap ; //使用map加快查詢