LFU算法实现

这一篇实现主要实现了最不常用算法

#include <iostream>
#include <string>
#include <unordered_map>
using namespace std;

struct ColumnNode {
	int val;
	string key;
	unsigned int freq;
	ColumnNode* last;
	ColumnNode* next;
	ColumnNode(string key, int value)
		: val(value), key(key), freq(1), last(nullptr), next(nullptr)
	{ }
};

struct RowNode {
	ColumnNode* head;
	ColumnNode* tail;
	RowNode* last;
	RowNode* next;

	RowNode(ColumnNode* node) 
		: last(nullptr), next(nullptr) {
		if (node == nullptr) {
			return;
		}
		head = tail = node;
	}

	void addColumnNode(ColumnNode* node) {
		if (node == nullptr) {
			return;
		}
		node->next = head;
		head->last = node;
		head = node;
	}

	void deleteColumnNode(ColumnNode* node) {
		if (node == nullptr) {
			return;
		}

		if (head == tail) {
			head = tail = nullptr;
		}
		else {
			if (node == head) {
				head = head->next;
				head->last = nullptr;
			}
			else if (node == tail) {
				tail = tail->last;
				tail->next = nullptr;
			}
			else {
				node->last->next = node->next;
				node->next->last = node->last;
			}
		}
		node->last = node->next = nullptr;
	}

	bool columnListIsEmpty() {
		return head == nullptr;
	}

	~RowNode() {
		while (head) {
			tail = head;
			head = head->next;
			delete tail;
		}
	}
};

class LFUCache {
public:
	LFUCache(int capacity)
		: capacity(capacity), size(0), rowListHead(nullptr)
	{ }

	void moveNode(ColumnNode* node, RowNode* oldRowNode) {
		oldRowNode->deleteColumnNode(node);
		RowNode* nextRowNode = oldRowNode->next;
		RowNode* preRowNode = motifyHeadList(oldRowNode);
		if (nextRowNode == nullptr) {
			RowNode* newRowNode = new RowNode(node);
			if (preRowNode != nullptr) {
				preRowNode->next = newRowNode;
			}
			newRowNode->last = preRowNode;
			if (rowListHead == nullptr) {
				rowListHead = newRowNode;
			}
			heads.insert(pair<ColumnNode*, RowNode*>(node, newRowNode));
		}
		else {
			if (nextRowNode->head->freq == node->freq) {
				nextRowNode->addColumnNode(node);
				heads.insert(pair<ColumnNode*, RowNode*>(node, nextRowNode));
			}
			else {
				RowNode* newRowNode = new RowNode(node);
				newRowNode->next = nextRowNode;
				nextRowNode->last = newRowNode;
				newRowNode->last = preRowNode;
				if (preRowNode) {
					preRowNode->next = newRowNode;
				}
				if (rowListHead == nextRowNode) {
					rowListHead = newRowNode;
				}
				heads.insert(pair<ColumnNode*, RowNode*>(node, newRowNode));
			}
		}
	}

	RowNode* motifyHeadList(RowNode* rowNode) {
		if (rowNode->columnListIsEmpty()) {
			if (rowNode == rowListHead) {
				rowListHead = rowListHead->next;
				if (rowListHead) {
					rowListHead->last = nullptr;
				}
			}
			else {
				rowListHead->last->next = rowListHead->next;
				if (rowListHead->next) {
					rowListHead->next->last = rowListHead->last;
				}
			}
			RowNode* res = rowNode->last;
			delete rowNode;
			return res;
		}
		return rowNode;
	}

	void set(string key, int value) {
		if (records.count(key)) {
			ColumnNode* node = records.at(key);
			node->val = value;
			node->freq++;
			RowNode* rowNode = heads.at(node);
			moveNode(node, rowNode);
		}
		else {
			if (capacity == size) {
				ColumnNode* columnNode = rowListHead->tail;
				rowListHead->deleteColumnNode(columnNode);
				records.erase(key);
				RowNode* rowNode = heads.at(columnNode);
				heads.erase(columnNode);
				motifyHeadList(rowNode);
				delete columnNode;
				size--;
			}
			ColumnNode* node = new ColumnNode(key, value);
			if (rowListHead == nullptr) {
				rowListHead = new RowNode(node);
			}
			else {
				if (rowListHead->head->freq == 1) {
					rowListHead->addColumnNode(node);
				}
				else {
					RowNode* newRowNode = new RowNode(node);
					newRowNode->next = rowListHead;
					rowListHead->last = newRowNode;
					rowListHead = newRowNode;
				}
			}
			records.insert(pair<string, ColumnNode*>(key, node));
			heads.insert(pair<ColumnNode*, RowNode*>(node, rowListHead));
			size++;
		}
	}

	int get(string key) {
		if (records.count(key) == 0) {
			return INT_MIN;
		}
		ColumnNode* columnNode = records.at(key);
		columnNode->freq++;
		RowNode* rowNode = heads.at(columnNode);
		moveNode(columnNode, rowNode);
		return columnNode->val;
	}

	~LFUCache() {
		while (rowListHead) {
			RowNode* rowNode = rowListHead;
			rowListHead = rowListHead->next;
			delete rowNode;
		}
	}

private:
	int size;
	int capacity;
	RowNode* rowListHead;
	unordered_map<string, ColumnNode*> records;
	unordered_map<ColumnNode*, RowNode*> heads;
};

int main() {
	LFUCache lFUCache(3);
	lFUCache.set(string("A"), 1);
	lFUCache.set(string("B"), 2);
	lFUCache.set(string("C"), 3);
	lFUCache.get(string("A"));
	lFUCache.set(string("D"), 4);
	system("pause");
	return 0;
}

如有侵权,请联系删除,如有错误,欢迎大家指正,谢谢

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值