LRU Cache实现

最近在看Leveldb源码,里面用到LRU(Least Recently Used)缓存,所以自己动手来实现一下。LRU Cache通常实现方式为Hash Map + Double Linked List,我使用std::map来代替哈希表。

实现代码如下:

#include <iostream>
#include <map>
#include <assert.h>

using namespace std;

// define double linked list node
template<class K, class V>
struct Node{
	K key;
	V value;
	Node *pre_node;
	Node *nxt_node;
	Node() : key(K()), value(V()), pre_node(0), nxt_node(0){}
};

// define LRU cache.
template<class K, class V>
class LRUCache{
public:
	typedef Node<K, V> CacheNode;
	typedef map<K, CacheNode*> HashTable;

	LRUCache(const int size) : capacity(size), count(0), head(0), tail(0){
		head = new CacheNode;
		tail = new CacheNode;
		head->nxt_node = tail;
		tail->pre_node = head;
	}
	~LRUCache(){
		HashTable::iterator itr = key_node_map.begin();
		for (itr; itr != key_node_map.end(); ++itr)
			delete itr->second;
		delete head;
		delete tail;
	}

	void put(const K &key, const V &value){
		// check if key already exist.
		HashTable::const_iterator itr = key_node_map.find(key);
		if (itr == key_node_map.end()){
			CacheNode *node = new CacheNode;
			node->key = key;
			node->value = value;
			if (count == capacity)
			{
				CacheNode *tail_node = tail->pre_node;
				extricateTheNode(tail_node);
				key_node_map.erase(tail_node->key);
				delete tail_node;
				count--;
			}

			key_node_map[key] = node;
			count++;
			moveToHead(node);
		}
		else{
			itr->second->value = value;
			extricateTheNode(itr->second);
			moveToHead(itr->second);
		}
	}

	V get(const K &key){
		// check if key already exist.
		HashTable::const_iterator itr = key_node_map.find(key);
		if (itr == key_node_map.end()){
			return V();
		}
		else{
			extricateTheNode(itr->second);
			moveToHead(itr->second);
			return itr->second->value;
		}
	}

	void print(){
		if (count == 0)
			cout << "Empty cache." << endl;

		cout << "Cache information:" << endl;
		cout << "  " << "capacity: " << capacity << endl;
		cout << "  " << "count: " << count << endl;
		cout << "  " << "map size: " << key_node_map.size() << endl;
		cout << "  " << "keys: ";
		CacheNode *node = head;
		while (node->nxt_node != tail)
		{
			cout << node->nxt_node->key << ",";
			node = node->nxt_node;
		}
		cout << endl;
	}

private:
	void moveToHead(CacheNode *node){
		assert(head);
		node->pre_node = head;
		node->nxt_node = head->nxt_node;
		head->nxt_node->pre_node = node;
		head->nxt_node = node;
	}
	void extricateTheNode(CacheNode *node){ // evict the node from the list.
		assert(node != head && node != tail);
		node->pre_node->nxt_node = node->nxt_node;
		node->nxt_node->pre_node = node->pre_node;
	}

private:
	int capacity;
	int count;
	Node<K, V> *head;
	Node<K, V> *tail;
	HashTable key_node_map;
};

int main()
{
	LRUCache<int, int> my_cache(4);

	for (int i = 0; i < 20; ++i)
	{
		int key = rand() % 10 + 1;
		int value = key * 2;
		cout << "Put[" << key << "," << value << "]>>>" << endl;
		my_cache.put(key, value);
		my_cache.print();
	}

	for (int i = 0; i < 20; ++i)
	{
		int key = rand() % 10 + 1;
		int value = my_cache.get(key);
		cout << "Get value of " << key << ": " << value << ".>>>" << endl;
		my_cache.print();
	}

	return 0;
}
时间: 2024-10-16 04:58:17

LRU Cache实现的相关文章

146. LRU Cache

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put. get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1. put

【Lintcode】LRU Cache, Data Stream Median

主要是priority_queue的用法 一个是内置类型优先队列怎么设置小根堆(默认大根堆) 如果是自定义数据结构,有两种办法 1.定义这种数据结构的比较符号,就可以当成内置类型整 2.传进去一个重载()的类,当小于号用,默认还是大根堆,也许传进去的是个callable object都行的吧,我试了一下函数好像不行,不懂,不管了 LRU Cache class LRUCache{ public: // @param capacity, an integer int Time; typedef i

LRU Cache的简单实现

Cache这个东西可以说无处不在,处理器中的TLB,Linux系统中的高速页缓存,还有很多人熟知的开源软件memcached,都是cache的一种实现.LRU是Least Recently Used的缩写,即最近最少使用,是常用cache算法中的一种.因为cache的存储空间相对于后端存储来说更有限,将cache空间和后端存储空间映射后,还需要一些算法来解决cache满的问题并保证效率,LRU就是在cache满了以后,将最近最少访问到的内容移除,然后将新的内容放入cache,新的内容也成为了最近

【LRU Cache】cpp

题目: 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.

LRU Cache (9)

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

[leetcode]LRU Cache (python)

LRU:最近最久未使用,为了得到这个最新最久的信息,需要一种策略来进行记录,如果加入类似时间戳式的字段,那么每次删除的时候,就必须通过遍历才能得到时间信息,或者对时间戳进行排序,但是无论哪种,都是需要额外的维护,维护成本都比较高. 广泛使用的策略是底层用双端队列来进行维护,双端使得在插入删除时操作更简单.而单单使用双端队列似乎还是不够,比如在get 时,还是需要顺序查找给定的key参数的,所以为了能在O(1) 时间获得key 需要类hash的结构,在python里,就用字典. 接下来的事情是,我

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(

LeetCode——LRU Cache

Description: 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 r

LRU算法 - LRU Cache

这个是比较经典的LRU(Least recently used,最近最少使用)算法,算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”. 一般应用在缓存替换策略中.其中的”使用”包括访问get和更新set. LRU算法 LRU是Least Recently Used 近期最少使用算法.内存管理的一种页面置换算法,对于在内存中但又不用的数据快(内存块)叫做LRU,Oracle会根据那些数据属于LRU而将其移出内存而腾出空间来加载另外的数据,一

Java for LeetCode 146 LRU Cache 【HARD】

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