多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > 互聯網 > 使用C++實現一個LRU cache

使用C++實現一個LRU cache

來源:程序員人生   發布時間:2014-10-20 08:00:01 閱讀次數:3196次

什么是LRU Cache

LRU是Least Recently Used的縮寫,意思是最近最少使用,它是一種Cache替換算法。什么是Cache?狹義的Cache指的是位于CPU和主存間的快速RAM,通常它不像系統主存那樣使用DRAM技術,而使用昂貴但較快速的SRAM技術。廣義上的Cache指的是位于速度相差較大的兩種硬件之間,用于協調兩者數據傳輸速度差異的結構。除了CPU與主存之間有Cache,內存與硬盤之間也有Cache,乃至在硬盤與網絡之間也有某種意義上的Cache──稱為Internet臨時文件夾或網絡內容緩存等。

Cache的容量有限,因此當Cache的容量用完后,而又有新的內容需要添加進來時,就需要挑選并舍棄原有的部分內容,從而騰出空間來放新內容。LRU Cache的替換原則就是將最近最少使用的內容替換掉。其實,LRU譯成最久未使用會更形象,因為該算法每次替換掉的就是一段時間內最久沒有使用過的內容。

數據結構

LRU的典型實現是hash map + doubly linked list,雙向鏈表用于存儲數據結點,并且它是按照結點最近被使用的時間來存儲的。如果一個結點被訪問了,我們有理由相信它在接下來的一段時間被訪問的概率要大于其它結點。于是,我們把它放到雙向鏈表的頭部。當我們往雙向鏈表里插入一個結點,我們也有可能很快就會使用到它,同樣把它插入到頭部。我們使用這種方式不斷地調整著雙向鏈表,鏈表尾部的結點自然也就是最近一段時間,最久沒有使用到的結點。那么,當我們的Cache滿了,需要替換掉的就是雙向鏈表中最后的那個結點(不是尾結點,頭尾結點不存儲實際內容)。

如下是雙向鏈表示意圖,注意頭尾結點不存儲實際內容:

頭 --> 結 --> 結 --> 結 --> 尾
結       點        點       點       結
點 <-- 1  <-- 2 <-- 3  <-- 點

假如上圖Cache已滿了,我們要替換的就是結點3。

哈希表的作用是什么呢?如果沒有哈希表,我們要訪問某個結點,就需要順序地一個個找,時間復雜度是O(n)。使用哈希表可以讓我們在O(1)的時間找到想要訪問的結點,或者返回未找到。

Cache接口

Cache主要有兩個接口:

T Get(K key);
void Put(K key, T data);

當我們通過鍵值來訪問類型為T的數據時,調用Get函數。如果鍵值為key的數據已經在Cache中,那就返回該數據,同時將存儲該數據的結點移到雙向鏈表頭部。如果我們查詢的數據不在Cache中,我們就可以通過Put接口將數據插入雙向鏈表中。如果此時的Cache還沒滿,那么我們將新結點插入到鏈表頭部,同時用哈希表保存結點的鍵值及結點地址對。如果Cache已經滿了,我們就將鏈表中的最后一個結點(注意不是尾結點)的內容替換為新內容,然后移動到頭部,更新哈希表。

C++代碼

注意,hash map并不是C++標準的一部分,我使用的是Linux下g++ 4.6.1,hash_map放在/usr/include/c++/4.6/ext下,需要使用__gnu_cxx名空間,Linux平臺可以切換到c++的include目錄:cd /usr/include/c++/版本然后grep -iR “hash_map” ./查看在哪個文件中,一般頭文件的最后幾行會提示它所在的名空間。其它平臺請自行探索。XD

當然如果你已經很fashion地在使用C++ 11,就不會有這些小困擾了。

// A simple LRU cache written in C++ // Hash map + doubly linked list #include <iostream> #include <vector> #include <ext/hash_map> using namespace std; using namespace __gnu_cxx; template <class K, class T> struct Node{ K key; T data; Node *prev, *next; }; template <class K, class T> class LRUCache{ public: LRUCache(size_t size){ entries_ = new Node<K,T>[size]; for(int i=0; i<size; ++i)// 存儲可用結點的地址 free_entries_.push_back(entries_+i); head_ = new Node<K,T>; tail_ = new Node<K,T>; head_->prev = NULL; head_->next = tail_; tail_->prev = head_; tail_->next = NULL; } ~LRUCache(){ delete head_; delete tail_; delete[] entries_; } void Put(K key, T data){ Node<K,T> *node = hashmap_[key]; if(node){ // node exists detach(node); node->data = data; attach(node); } else{ if(free_entries_.empty()){// 可用結點為空,即cache已滿 node = tail_->prev; detach(node); hashmap_.erase(node->key); } else{ node = free_entries_.back(); free_entries_.pop_back(); } node->key = key; node->data = data; hashmap_[key] = node; attach(node); } } T Get(K key){ Node<K,T> *node = hashmap_[key]; if(node){ detach(node); attach(node); return node->data; } else{// 如果cache中沒有,返回T的默認值。與hashmap行為一致 return T(); } } private: // 分離結點 void detach(Node<K,T>* node){ node->prev->next = node->next; node->next->prev = node->prev; } // 將結點插入頭部 void attach(Node<K,T>* node){ node->prev = head_; node->next = head_->next; head_->next = node; node->next->prev = node; } private: hash_map<K, Node<K,T>* > hashmap_; vector<Node<K,T>* > free_entries_; // 存儲可用結點的地址 Node<K,T> *head_, *tail_; Node<K,T> *entries_; // 雙向鏈表中的結點 }; int main(){ hash_map<int, int> map; map[9]= 999; cout<<map[9]<<endl; cout<<map[10]<<endl; LRUCache<int, string> lru_cache(100); lru_cache.Put(1, "one"); cout<<lru_cache.Get(1)<<endl; if(lru_cache.Get(2) == "") lru_cache.Put(2, "two"); cout<<lru_cache.Get(2); return 0; }

解析:
首先使用鏈表來管理所有的已經使用或正在使用的節點(也就是物理內存頁),剛開始分配了一些節點,存放在向量中,在緩沖沒有使用完之前都是在向量中存放著,當向量中
的緩沖使用完了,那么就必須從鏈表中的最后一個取出來當做新的節點來使用。在查找節點在鏈表中的位置時,如果每次都是從頭來查找的話,效率會很低,所以使用了
hash_map來管理鏈表中的所有節點,hash_map中都是使用過的節點,在查找時很方便。
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 国产成人精品免费视频大全办公室 | 黄色网址网站在线观看 | 亚洲欧洲久久久精品 | 日韩毛片欧美一级a | 久久93精品国产91久久综合 | www.色网站| 在线观看中文字幕 | 欧美色图校园春色 | 亚洲精品乱码久久久久久蜜桃欧美 | 爱插综合网 | 在线一区二区三区 | 精品一区二区三区在线视频 | 久久国产精品亚洲 | 中文字幕免费视频精品一 | 亚洲国产欧美日韩精品小说 | 一本久道热中字伊人 | 最近中文字幕高清mv免费 | 中文字幕亚洲无线码a | 拍拍拍无挡视频免费全程1000 | xxx在线视频| 亚洲区欧美区 | 欧美成人aaaa免费高清 | 欧美性猛交黑人 | 717影院理论午夜伦不卡久久 | 国产a不卡片精品免费观看 国产a国产片色老头 | 伊人久久大香线蕉 | 国产一区二区亚洲精品 | 暖暖在线精品日本中文 | 国产成人精品一区二区不卡 | www.操.com| 国产精品99爱免费视频 | 亚洲天堂成人网 | 久爱精品| 亚洲永久精品一区二区三区 | 国产第一页在线视频 | 欧美在线精品一区二区三区 | 精品久久久99大香线蕉 | 国内精品18videosex性欧美 | 免费视频爱爱 | 狼人天堂网 | a毛片免费看 |