力扣 LRU缓存-146
LRU缓存-146
/*
定义双向链表节点,用于存储缓存中的每个键值对。
成员变量:key和value存储键值对。preb和next指向前一个和后一个节点,形成双向链表。
构造函数:默认构造函数:初始化空节点。参数化构造函数:初始化带有特定键值的节点。
*/
struct LinksNode{int key,value;LinksNode* prev;LinksNode* next;LinksNode():key(0),value(0),prev(nullptr),next(nullptr){}LinksNode(int _key,int _value):key(_key),value(_value),prev(nullptr),next(nullptr){}
};
class LRUCache {
private:
/*
定义LRUCache类的成员变量和构造函数
成员变量: cache:哈希表,键时缓存的key,值是链表节点的指针,用于快速定位节点。head和tail:伪头部和伪尾部节点,用于简化链表操作。size:当前缓存的大小。capacity:缓存的容量。
*/map<int,LinksNode*> cache;LinksNode* head;LinksNode* tail;int size = 0;int capacity = 0;
public:
/*
构造函数:初始化缓存的容量为 _capacity。创建两个特殊的伪节点head和tail,不存储数据,用于简化链表的插入和删除操作。head->next指向tail,tail->prev指向head,形成一个空的双向链表。
*/LRUCache(int _capacity):capacity(_capacity) {head = new LinksNode();tail = new LinksNode();head->next = tail;tail->prev = head;}
/*
获取指定键的值
如果键不存在,返回-1.
如果键存在:使用哈希表cache快速定位节点。调用moveToHead(node)将节点移动到链表头部,表示最近被访问。返回节点的值。
*/int get(int key) {if(!cache.count(key))return -1;else{LinksNode* node = cache[key];moveToHead(node); return node->value; }}
/*
插入新的键值对或更新已有键值对。
1.键不存在:创建一个新节点并插入到链表头部。添加到哈希表。如果超出容量:调用removeTail()删除最久未使用的节点。从哈希表中移除相应的键值对。
2.键已存在更新对应节点的值。调用moveToHead()将节点移动到链表头部
*/void put(int key, int value) {if(!cache.count(key)){LinksNode* node = new LinksNode(key,value);addToHead(node);cache[key] = node;++size;if(size>capacity){LinksNode* re = removeTail();//返回链表尾部被删除的键cache.erase(re->key);delete re;--size;}}else{LinksNode* node = cache[key];node->value = value;moveToHead(node);}}
/*
将一个节点插入到链表的头部设置新节点的 prev 为 head,next 为 head->next。更新原先头部节点的 prev 为新节点。更新 head->next 为新节点。
*/void addToHead(LinksNode* node){node->prev = head;node->next = head->next;head->next->prev = node;head->next = node;}
/*
从链表中删除指定节点:更新节点前后连接:node->prev->next = node->next和node->next->prev = node->prev。节点 node 与链表完全断开。
*/void removeNode(LinksNode* node){node->prev->next = node->next;node->next->prev = node->prev;}
/*
将指定节点移动到链表头部:调用 removeNode(node) 将节点从原位置移除。调用 addToHead(node) 将节点插入到链表头部。
*/void moveToHead(LinksNode* node){removeNode(node);addToHead(node);}
/*
删除链表的尾部节点(最久未使用的节点)并返回:找到伪尾部节点之前的节点:tail->prev。调用 removeNode(node) 将其从链表中移除。返回该节点,供 put 函数释放资源。
*/LinksNode* removeTail(){LinksNode* node = tail->prev;removeNode(node);return node;}
};
每日问题
什么是 C++ 中的智能指针?有哪些类型的智能指针?
C++中的智能指针是一种用于管理动态内存的工具,它封装了裸指针(raw pointer),并通过 RAII(资源获取即初始化)的方式自动管理资源的生命周期,从而避免了内存泄漏和悬空指针问题。
智能指针在头文件 中定义,常见的智能指针有三种:std::unique_ptr、std::shared_ptr 和 std::weak_ptr。
智能指针的特点
1.自动管理资源:
2.避免内存泄漏:无需手动调用 delete,减少资源管理的复杂度和错误风险。
3.指针行为:智能指针提供类似裸指针的操作(如 * 和 ->),使用方便。
智能指针的类型
1. std::unique_ptr
特点:
独占所有权,不能共享。
一个资源只能被一个 std::unique_ptr 管理。
不可复制,但可以通过 std::move 转移所有权。
适用场景:
确保某个资源只需一个所有者。
管理动态分配的内存,避免手动释放。
代码示例
#include <memory>
#include <iostream>int main() {std::unique_ptr<int> ptr = std::make_unique<int>(42); // 创建并管理资源std::cout << *ptr << std::endl;// std::unique_ptr<int> ptr2 = ptr; // 错误:不可复制std::unique_ptr<int> ptr2 = std::move(ptr); // 转移所有权if (!ptr) std::cout << "ptr is now null." << std::endl;
}
2. std::shared_ptr
特点:
支持共享所有权。
多个 std::shared_ptr 可以共享一个资源,内部使用引用计数管理资源。
当引用计数变为 0 时,资源被释放。
适用场景:
需要多个对象共享同一个资源。
不明确资源的生命周期,但确保资源在最后一个使用者销毁时释放。
代码示例:
#include <memory>
#include <iostream>int main() {std::shared_ptr<int> ptr1 = std::make_shared<int>(42); // 创建并共享资源std::shared_ptr<int> ptr2 = ptr1; // 共享所有权std::cout << "Value: " << *ptr1 << ", Ref count: " << ptr1.use_count() << std::endl;
}
3. std::weak_ptr
特点:
弱引用,不影响资源的引用计数。
依赖于 std::shared_ptr,通常用于解决循环引用问题。
需要通过 lock() 方法将 std::weak_ptr 转换为 std::shared_ptr 访问资源。
适用场景:
配合 std::shared_ptr 使用,避免循环引用。
希望访问资源但不影响资源的生命周期。
代码示例:
#include <memory>
#include <iostream>int main() {std::shared_ptr<int> sp = std::make_shared<int>(42);std::weak_ptr<int> wp = sp; // 弱引用,不增加引用计数std::cout << "Shared count: " << sp.use_count() << std::endl;if (auto locked = wp.lock()) { // 转换为 std::shared_ptrstd::cout << "Value: " << *locked << std::endl;} else {std::cout << "Resource is expired." << std::endl;}
}
智能指针的注意事项
不要混用裸指针和智能指针:
避免循环引用:使用 std::weak_ptr 打破 std::shared_ptr 的循环引用。
性能问题:std::shared_ptr 和 std::weak_ptr 引入了额外的引用计数开销,使用时需注意性能影响。
移动语义和拷贝语义有什么区别?
拷贝语义
在 C++ 中,移动语义和拷贝语义是处理对象所有权和资源管理的两种机制。它们的核心区别在于资源的分配方式和所有权转移是否发生。以下是它们的详细对比:
拷贝语义:
1.定义
拷贝语义通过复制对象的数据来创建一个新的对象。拷贝后的两个对象互不影响,拥有各自的资源。
2.实现方式
调用拷贝构造函数T(const T&)。
调用拷贝赋值运算符T& operator=(const T&)。
3.资源处理
资源完全被复制(例如深拷贝)。
每个对象独立管理自己的资源。
拷贝语义不会修改原对象的状态。
4.适用场景
对象的数据需要完整保留。
对象的数据较小,或者深拷贝的成本较低。
5.示例
class MyClass {
private:int* data;public:MyClass(int value) : data(new int(value)) {}// 拷贝构造函数(深拷贝)MyClass(const MyClass& other) : data(new int(*other.data)) {}// 拷贝赋值运算符(深拷贝)MyClass& operator=(const MyClass& other) {if (this == &other) return *this;delete data; // 释放原有资源data = new int(*other.data); // 复制新资源return *this;}~MyClass() { delete data; }
};
移动语义
1.定义
移动语义通过转移对象的资源来创建一个新对象,而不是复制数据。转移后,原对象的状态变为不可用或空。
2.实现方式
调用移动构造函数T(T&&)。
调用移动赋值运算符T& operator=(T&&)。
3.资源处理
资源被转移到新对象(例如指针的所有权转移)。
避免了资源的深拷贝,提高了性能。
转移后,原对象被置为安全状态(如 nullptr)。
4.适用场景
对象的数据较大,深拷贝成本高。
对象的资源需要高效管理(如动态内存、文件句柄等)。
5.示例
class MyClass {
private:int* data;public:MyClass(int value) : data(new int(value)) {}// 移动构造函数MyClass(MyClass&& other) noexcept : data(other.data) {other.data = nullptr; // 转移后,清空原对象的数据指针}// 移动赋值运算符MyClass& operator=(MyClass&& other) noexcept {if (this == &other) return *this;delete data; // 释放原有资源data = other.data; // 转移资源other.data = nullptr; // 清空原对象的数据指针return *this;}~MyClass() { delete data; }
};
典型应用场景
1.拷贝语义:
必须要保留多个对象副本时。
数据较小,深拷贝开销可以忽略。
2.移动语义:
临时对象的资源管理(如 std::move)。
对象资源较大,深拷贝开销不可忽略(如容器 std::vector、std::string)。
相关文章:

力扣 LRU缓存-146
LRU缓存-146 /* 定义双向链表节点,用于存储缓存中的每个键值对。 成员变量:key和value存储键值对。preb和next指向前一个和后一个节点,形成双向链表。 构造函数:默认构造函数:初始化空节点。参数化构造函数࿱…...

Elasticsearch简介与实操
Elasticsearch是一个分布式、高扩展、高实时的搜索与数据分析引擎。以下是对Elasticsearch的详细介绍: 一、基本概述 Elasticsearch是Elastic Stack(以前称为ELK Stack)的核心组件,Logstash和Beats有助于收集、聚合和丰富数据并将…...

用python将一个扫描pdf文件改成二值图片组成的pdf文件
使用墨水屏读书现在似乎越来越流行,这确实有一定的好处,例如基本不发热,电池续航时间超长,基本不能游戏所以有利于沉浸式阅读,还有不知道是不是真的有用的所谓防蓝光伤害。但是,如果阅读的书籍是扫描图片组…...

Failed to start Docker Application Container Engine
说明: 1)访问应用业务,读取不到数据,show databases;查看数据库报错 2)重启docker服务,服务启动失败,查看日志报错如下图所示 3)报错信息:chmod /data/docker: read-only…...

ESLint的简单使用(js,ts,vue)
一、ESLint介绍 1.为什么要用ESLint 统一团队编码规范(命名,格式等) 统一语法 减少git不必要的提交 减少低级错误 在编译时检查语法,而不是等js引擎运行时才检查 2.eslint用法 可以手动下载配置 可以通过vue脚手架创建项…...

实景三维赋能国土空间智慧治理
随着城市化进程的不断推进,国土空间的合理规划与高效管理成为政府面临的一项重大挑战。在这个过程中,实景三维技术作为一种新兴的信息技术手段,正在逐渐改变传统国土空间治理的方式,为智慧城市的建设提供了新的可能。本文旨在探讨…...

树链剖分(重链剖分)
树链剖分的核心思想就是将一棵树剖分成一条一条的链 因为树不好处理 但链比较好处理 为了学会它 我们先要学会树上dfs(深度优先搜索) 然后就没了(雾) Because 树链剖分需要用到两个dfs 哦对了 我们还要了解以下的知识点 1.子…...

幻读是什么?用什么隔离级别可以防止幻读?
幻读是什么? 幻读(Phantom Read) 是数据库事务中的一种现象,指的是在一个事务中,当执行两次相同的查询时,第二次查询返回的结果集包含了第一次查询中不存在的行,或者第一次查询中存在的行在第二…...

[Unity Demo]从零开始制作空洞骑士Hollow Knight第二十集:制作专门渲染HUD的相机HUD Camera和画布HUD Canvas
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、制作HUD Camera以及让两个相机同时渲染屏幕二、制作HUD Canvas 1.制作法力条Soul Orb引入库2.制作生命条Health读入数据3.制作吉欧统计数Geo Counter4.制作…...

智能安全配电装置在高校实验室中的应用
摘要:高校实验室是科研人员进行科学研究和实验的场所,通常会涉及到大量的仪器设备和电气设备。电气设备的使用不当或者维护不周可能会引发火灾事故。本文将以一起实验室电气火灾事故为例,对事故原因、危害程度以及防范措施进行分析和总结…...

网络安全等级保护测评机构管理办法(全文)
网络安全等级保护测评机构管理办法(公信安〔2018〕765号) 第一章 总则 第一条 为加强网络安全等级保护测评机构(以下简称“测评机构”)管理,规范测评行为,提高等级测评能力和服务水平,根据《中华人民共和国网络安全法…...

Flutter:shared_preferences数据存储,数据持久化,token等信息存储
官方示例:简单调用 // 初始化示例 final SharedPreferences prefs await SharedPreferences.getInstance(); // 存int await prefs.setInt(counter, 10); // 存bool await prefs.setBool(repeat, true); // 存double await prefs.setDouble(decimal, 1.5); // 存st…...

FileProvider高版本使用,跨进程传输文件
高版本的android对文件权限的管控抓的很严格,理论上两个应用之间的文件传递现在都应该是用FileProvider去实现,这篇博客来一起了解下它的实现原理。 首先我们要明确一点,FileProvider就是一个ContentProvider,所以需要在AndroidManifest.xml里面对它进行声明: <provideran…...

python学习记录18
1 函数的定义 python中的函数指使用某个定义好的名字指代一段完整的代码,在使用名字时可以直接调用整个代码,这个名字叫做函数名。利用函数可以达到编写一次即可多次调用的操作,从而减少代码量。 函数分为内置函数与自定义函数。内置函数例…...

云原生之k8s服务管理
文章目录 服务管理Service服务原理ClusterIP服务 对外发布应用服务类型NodePort服务Ingress安装配置Ingress规则 Dashboard概述 认证和授权ServiceAccount用户概述创建ServiceAccount 权限管理角色与授权 服务管理 Service 服务原理 容器化带来的问题 自动调度:…...

redis工程实战介绍(含面试题)
文章目录 redis单线程VS多线程面试题**redis是多线程还是单线程,为什么是单线程****聊聊redis的多线程特性和IO多路复用****io多路复用模型****redis如此快的原因** BigKey大批量插入数据测试数据key面试题海量数据里查询某一固定前缀的key如果生产上限值keys * ,fl…...

再次讨论下孤注一掷
在孤注一掷中的黑客技术里面,简单介绍了电影孤注一掷中用的一些"黑科技",这里继续讨论下,抛弃这些黑科技,即使在绝对公平的情况下,你也一样赢不了赌场 相对论有一个假设就是光速不变,这里也有个…...

LeetCode46.全排列
LeetCode刷题记录 文章目录 📜题目描述💡解题思路⌨C代码 📜题目描述 给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例1 输入:nums [1,2,3] 输出:[[1,2,…...

蓝桥杯-洛谷刷题-day4(C++)
目录 1.高精度乘法 i.P1303 A*B Problem高精度乘法 2.P4924 [1007] 魔法少女小Scarlet i.题目 ii.代码 3.二维数组 i.二维数组的建立 ii.备份 iii.二维数组的转动 4.指令的及时处理 1.高精度乘法 即,将每一位变为数组中的一位,并在数组中以倒序排列&a…...

c++总复习
1. C 中的移动语义及其作用 定义 移动语义是 C 11 引入的一种重要特性,它用于优化对象的资源管理,特别是在涉及对象所有权转移的场景中。传统的 C 语义在对象赋值或传递给函数时,通常会进行拷贝操作,即创建源对象的一个完整副本&…...

设计模式之策略模式-工作实战总结与实现
文章目录 应用场景存在问题解决方案继续延伸 应用场景 假设有这样的业务场景,大数据系统把文件推送过来,根据不同类型采取不同的解析方式。多数的小伙伴就会写出以下的代码: public class Question {public static void main(String[] args…...

E - 11/22 Subsequence题解
文章目录 大致思路代码 大致思路 预处理: 用pos1, pos2, posls 分别记录 1 1 1, 2 2 2 , / / / 在字符串中的『位置』 用cum1 和 cum2 分别存储了 1 1 1 和 2 2 2 的前缀和,这样可以快速获取任意区间内的 1 1 1 和 2 2 2 的『数量』 查询处理: 对于每个查询…...

PyPI 攻击:ChatGPT、Claude 模仿者通过 Python 库传播 JarkaStealer
《Java代码审计》http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247484219&idx1&sn73564e316a4c9794019f15dd6b3ba9f6&chksmc0e47a67f793f371e9f6a4fbc06e7929cb1480b7320fae34c32563307df3a28aca49d1a4addd&scene21#wechat_redirect 《Web安全》h…...

单片机学习笔记 9. 8×8LED点阵屏
更多单片机学习笔记:单片机学习笔记 1. 点亮一个LED灯单片机学习笔记 2. LED灯闪烁单片机学习笔记 3. LED灯流水灯单片机学习笔记 4. 蜂鸣器滴~滴~滴~单片机学习笔记 5. 数码管静态显示单片机学习笔记 6. 数码管动态显示单片机学习笔记 7. 独立键盘单片机学习笔记 8…...

【大模型-智能体】AutoGen Studio测试和导出工作流程
1. 测试工作流程 AutoGen Studio允许用户针对任务交互式地测试工作流程,并审查由此产生的成果物(如图像、代码和文档)。此外用户还可以查看Agent工作流程在处理任务时的“内心独白”,并查看诸如运行成本(如回合数、令牌…...

【Linux】-学习笔记04
第十二章、磁盘管理 1.查看磁盘空间使用量 1.1df命令 作用: 列出文件系统的磁盘空间占用情况 df,disk free,通过文件系统来快速获取空间大小的信息,当我们删除一个文件的时候,这个文件 不是马上就在文件系统当中消…...

计算机网络:应用层知识点概述及习题
网课资源: 湖科大教书匠 1、概述 习题1 1 在计算机网络体系结构中,应用层的主要功能是 A. 实现进程之间基于网络的通信 B. 通过进程之间的交互来实现特定网络应用 C. 实现分组在多个网络上传输 D. 透明传输比特流 2 以下不属于TCP/IP体系结构应用层范畴…...

如何构建高效的接口自动化测试框架?
🍅 点击文末小卡片 ,免费获取软件测试全套资料,资料在手,涨薪更快 在选择接口测试自动化框架时,需要根据团队的技术栈和项目需求来综合考虑。对于测试团队来说,使用Python相关的测试框架更为便捷。无论选…...

【C++习题】10.反转字符串中的单词 lll
题目: 链接🔗:557.反转字符串中的单词 lll 题目: 代码: class Solution { public:void Reverse(string &s, int start, int end){char tmp;while(start < end){tmp s[start];s[start] s[end];s[end] tmp;…...

undefined symbol: __nvJitLinkComplete_12_4, version libnvJitLink.so.12 问题解决
在部署运行opencompass项目时遇到了如下报错: ImportError: /data/conda/envs/opencompass/lib/python3.10/site-packages/torch/lib/../../nvidia/cusparse/lib/libcusparse.so.12: undefined symbol: __nvJitLinkComplete_12_4, version libnvJitLink.so.12…...