【常数时间】LFU(Least Frequently Used)基于频次的缓存淘汰算法C++实现

struct LFUNode
{
	int freq;
	list<pair<int, int>> vals;
	LFUNode(int f = 0) : freq(f) { }
};

typedef list<LFUNode>::iterator iptr;
typedef list<pair<int, int>>::iterator jptr;
class LFUCache {
public:

	
	LFUCache(int capacity) : capacity_(capacity) { }

	int get(int key) {
		auto it = kv_.find(key);
		if (it == kv_.end())
			return -1;
		kv_[key] = promote(key);
		return kv_[key].second->second;
	}

	void put(int key, int value) {
		if (capacity_ <= 0)
			return;
		if (kv_.find(key) == kv_.end()) {
			// insert new element
			if (kv_.size() >= capacity_)
				evict();
			iptr i = cache_.begin();
			if (i == cache_.end() || i->freq != 1)
				i = cache_.insert(i, LFUNode(1));
			jptr j = i->vals.insert(i->vals.end(), { key,value });
			kv_[key] = { i, j };
		}
		else {
			kv_[key] = promote(key, value);
		}
	}
private:
	pair<iptr, jptr> promote(int key, int val = -1) {
		iptr i;
		jptr j;
		// unpack kv_[key]
		tie(i, j) = kv_[key];
		
		// k refers to the next element in bucket
		iptr k = next(i);

		// val == -1 means that get() invoked promote
		// so we don't need to change it's value
		if (val == -1)
			val = j->second;
		// retrive the frequence
		int freq = i->freq + 1;
		// erase the key-value pair in the list
		i->vals.erase(j);
		if (i->vals.empty())
			cache_.erase(i);
		// check to see if we need to create a new element
		if (k == cache_.end() || k->freq != freq)
			i = cache_.insert(k, LFUNode(freq));
		// if the slot already exists
		else
			i = k; // i points to k
		// append key-value pair in the list
		j = i->vals.insert(i->vals.end(), { key, val });
		// i->vals.emplace_back(key, j->second);
		// j = i->vals.end() - 1;
		return{ i,j };
	}

	void evict() {
		// i points to the first element of the frequency list
		// so i refers to the smallest frequency
		iptr i = cache_.begin();
		// j refers to the least recently used ket-value pair
		jptr j = i->vals.begin();
		// erase this pair in the map
		kv_.erase(j->first);
		// erase j
		i->vals.erase(j);
		// if there is no more pair in the i list
		// delete i
		if (i->vals.empty())
			cache_.erase(i);
	}
private:
	int capacity_;
	list<LFUNode> cache_;
	unordered_map<int, pair<iptr, jptr> > kv_;
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值