FJUTOJ-3682 LRU算法的实现2 (链表+哈希)
此题让我们实现一个LRU的模板类。本题较简便且高效的写法是维护一个std::list和一个std::unordered_map。
std::list 与 std::unordered_map 中存放的内容
std::list中存放各key,类型为K。链表中各键码存放的顺序是按照访问顺序存放的。
std::unordered_map中以key为第一维,第二维为一个pair,其first和second分别为:
first: 该key对应的value。
second:该key在std::list中的迭代器方便访问。
为方便,下面用“链表”来指代std::list,用“哈希表”来指代std::unordered_map。
各操作实现
insert操作:用哈希表判断该键是否已经存在。若存在,先在链表中删除该key,然后再新加一个该key到链表尾部,并更新在哈希表中的value和链表的迭代器。若不存在,则直接加至链表尾部,并在哈希表中插入该key,伴随着对应的value和链表迭代器。
get操作:直接从哈希表中获得其value即可。代码实现未检测该key是否存在,严谨来说应该加上异常处理。
contains操作:直接在哈希表中查询是否存在该key即可。
vis操作:用哈希表判断该键是否存在。若不存在,则本操作无效。否则,将该键从链表中删除,然后再将其加至链表尾部,并更新哈希表中对应链表迭代器。
pop操作:判断是否整个容器已经为空。若为空,则本操作无效。否则,将链表头部元素从链表中删除,并在哈希表中删除对应键值信息。
remove操作:用哈希表判断该键是否存在。若不存在,则本操作无效。否则,将该键从链表中删除,并在哈希表中删除对应键值信息。
empty操作:哈希表或链表判空即可。
size操作:取哈希表或链表大小即可。
clear操作:清空哈希表和链表即可。
时间复杂度
各操作基于对链表和哈希表的修改。期望复杂度均为\(O(1)\)。
参考代码实现
#include <list>
#include <unordered_map>
template <typename K, typename V>
class LRU {
private:
typedef typename std::list<K>::iterator listIter;
typedef typename std::unordered_map<K, std::pair<V, listIter>>::iterator unorderedMapIter;
std::list<K> lst;
std::unordered_map<K, std::pair<V, listIter>> mp;
public:
void insert(const K &key, const V &value) {
unorderedMapIter it = mp.find(key);
if (it == mp.end()) {
lst.emplace_back(key);
mp.insert(std::make_pair(key, std::make_pair(value, --lst.end())));
} else {
lst.erase(it->second.second);
lst.emplace_back(key);
it->second = std::make_pair(value, --lst.end());
}
}
// If Key doesn't exist, this will create one <Key, zero>
V get(const K &key) {
return mp[key].first;
}
bool contains(const K &key) {
return mp.count(key) == 1;
}
void vis(const K &key) {
unorderedMapIter it = mp.find(key);
if (it != mp.end()) {
lst.erase(it->second.second);
lst.emplace_back(key);
it->second.second = --lst.end();
}
}
void pop() {
if (!lst.empty()) {
mp.erase(lst.front());
lst.pop_front();
}
}
void remove(const K &key) {
unorderedMapIter it = mp.find(key);
if (it != mp.end()) {
lst.erase(it->second.second);
mp.erase(it);
}
}
bool emtpy() { // 注意本题要求函数名为emtpy
return lst.empty();
}
unsigned long long size() {
return lst.size();
}
void clear() {
lst.clear();
mp.clear();
}
};
FJUTOJ-3682 LRU算法的实现2 (链表+哈希)的更多相关文章
- java基础解析系列(四)---LinkedHashMap的原理及LRU算法的实现
java基础解析系列(四)---LinkedHashMap的原理及LRU算法的实现 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析 ...
- [整理] LRU 算法的实现方式
目录 概念 方法选择 实现方案(基于LinkedHashMap) 改进方案 1.LRU-K 2.Two queue 3.Multi Queue(MQ) LRU类算法对比 LRU 在 Redis 中的应 ...
- linkedhashmap中关于LRU算法的实现
//LinkedHashMap的一个构造函数,当参数accessOrder为true时,即会按照访问顺序排序,最近访问的放在最前,最早访问的放在后面 public LinkedHashMap(int ...
- Python学习(三) 八大排序算法的实现(下)
本文Python实现了插入排序.基数排序.希尔排序.冒泡排序.高速排序.直接选择排序.堆排序.归并排序的后面四种. 上篇:Python学习(三) 八大排序算法的实现(上) 1.高速排序 描写叙述 通过 ...
- Bug2算法的实现(RobotBASIC环境中仿真)
移动机器人智能的一个重要标志就是自主导航,而实现机器人自主导航有个基本要求--避障.之前简单介绍过Bug避障算法,但仅仅了解大致理论而不亲自动手实现一遍很难有深刻的印象,只能说似懂非懂.我不是天才,不 ...
- Canny边缘检测算法的实现
图像边缘信息主要集中在高频段,通常说图像锐化或检测边缘,实质就是高频滤波.我们知道微分运算是求信号的变化率,具有加强高频分量的作用.在空域运算中来说,对图像的锐化就是计算微分.由于数字图像的离散信号, ...
- SSE图像算法优化系列十三:超高速BoxBlur算法的实现和优化(Opencv的速度的五倍)
在SSE图像算法优化系列五:超高速指数模糊算法的实现和优化(10000*10000在100ms左右实现) 一文中,我曾经说过优化后的ExpBlur比BoxBlur还要快,那个时候我比较的BoxBlur ...
- 详解Linux内核红黑树算法的实现
转自:https://blog.csdn.net/npy_lp/article/details/7420689 内核源码:linux-2.6.38.8.tar.bz2 关于二叉查找树的概念请参考博文& ...
- 详细MATLAB 中BP神经网络算法的实现
MATLAB 中BP神经网络算法的实现 BP神经网络算法提供了一种普遍并且实用的方法从样例中学习值为实数.离散值或者向量的函数,这里就简单介绍一下如何用MATLAB编程实现该算法. 具体步骤 这里 ...
随机推荐
- OpenCV检测Marker位姿
Marker检测采用小觅相机,可以实时检测Marker的位置和姿态,效果如下: 参考代码如下: #include "pch.h" #include <Eigen/Dense& ...
- 00.JS前言
前言: 学习一门编程语言的基本步骤(01)了解背景知识 1.了解背景知识 1)什么是 JavaScript 语言? JavaScript 是一种轻量级的脚本语言.所谓“脚本语言”(scri ...
- 【WPF学习】第十七章 鼠标输入
鼠标事件执行几个关联的任务.当鼠标移到某个元素上时,可通过最基本的鼠标事件进行响应.这些事件是MouseEnter(当鼠标指针移到元素上时引发该事件)和MouseLeave(当鼠标指针离开元素时引发该 ...
- c++输入输出,保留几位小数
#include <iomanip> //头文件 //第一种写法 cout<<setiosflags(ios::); //第二种写法 cout.setf(ios::fixed) ...
- 解决visual studio 2013编译过程中存在的无法打开kernel.lib问题
1. 出现此类问题的原因 由于原visual studio文件中的安装中出现问题,所以原有的SDK(soft development kits)文件出现缺失: 2. 解决方法1 重新下载SDK工具,安 ...
- 关于将sublime中的代码高亮导出到博客中
第一步:打开sublime编辑器,用快捷键ctrl+shift+p调出control panel,在出现的输入框中输入install,按回车键 第二步:然后输入插件名称sublimehighlight ...
- C# WPF聊天界面(3/3)
微信公众号:Dotnet9,网站:Dotnet9,问题或建议:请网站留言, 如果对您有所帮助:欢迎赞赏. C# WPF聊天界面(3/3) 阅读导航 本文背景 代码实现 本文参考 1.本文背景 系列文章 ...
- phpcmsv9 后台统计编辑发稿数量
直切正题: 每个人,每个栏目,发稿数量统计 SELECT a.realname AS 姓名, c.catname AS 栏目名称, count(1) AS 发稿量FROM v9_news bz, v9 ...
- 怎样在GitHub上新建一个文件夹
GitHub如何创建文件夹 创建新文件的时候名字后面加个斜杠(/)就可以了 点击新建文件,输入文件名的时候后面加上斜杠/就是创建了一个文件夹,没有斜杠就是创建了一个文 创建好后点提交 Commit n ...
- 使用shell程序备份crontab中的.sh脚本文件
需求 线上环境有一些定时脚本(用crontab -l可查看当前用户的),有时我们可能会改这些定时任务的脚本内容.为避免改错无后悔药,需用shell实现一个程序,定时备份crontab中的.sh脚本文件 ...