当前位置: 首页 > news >正文

【百度】C++开发(25届提前批 一面)面经

文章目录

  • 1. 代码实现:说说LRU,并代码实现LRU
    • 为什么使用哈希表?(有两个原因)
      • 1. 仅用双向链表的缺陷
    • 2. 引入哈希表的作用
      • 1. 快速查找:
      • 2. 快速插入与删除:
    • 双向链表 + 哈希表的协作过程
    • 举例说明
    • 代码实现
  • 14、一个线程池应该包含什么?

1. 代码实现:说说LRU,并代码实现LRU

在这里插入图片描述

为什么使用哈希表?(有两个原因)

1. 仅用双向链表的缺陷

如果只使用双向链表来实现 LRU,每次你需要查找某个缓存键值时,必须从链表头部开始遍历,直到找到目标节点。这种操作的时间复杂度是 O(n),其中 n 是链表的长度,即缓存的大小。如果缓存很大,这种查找操作会变得非常慢。

例如:
假设你缓存了 1000 个键值对,要查找某个键时,你需要遍历 1000 个节点才能找到目标。这种线性查找效率非常低。

2. 引入哈希表的作用

哈希表(unordered_map)用于将键映射到双向链表中的节点,允许我们在 O(1) 的时间内直接找到双向链表中的目标节点。通过哈希表,避免了链表的线性查找。下面是哈希表在 LRU 实现中的几个作用:

1. 快速查找:

通过哈希表,你可以在 O(1) 的时间内直接定位到缓存中某个键对应的双向链表节点。例如,当你调用 get(key) 时,不需要遍历链表来查找,而是直接通过哈希表找到节点。

  • 没有哈希表时查找是 O(n)。
  • 有了哈希表后,查找是 O(1)。

2. 快速插入与删除:

当缓存中不存在某个键时,使用 put(key, value),可以通过哈希表快速将新节点插入双向链表,并将其键值存入哈希表;如果缓存满了,也可以通过哈希表在 O(1) 时间内定位到需要删除的节点,并将其从链表和哈希表中移除。

双向链表 + 哈希表的协作过程

在这里插入图片描述

举例说明

假设我们有一个容量为 2 的 LRU 缓存,操作过程如下:

  1. put(1, 1):插入键值对 (1, 1)。链表中插入新节点,同时将键 1 映射到该节点。
    - 链表:[1](1是最新的)
    - 哈希表:{1 -> 节点1}
  2. put(2, 2):插入键值对 (2, 2)。
    - 链表:[2, 1](2是最新的,1是次新的)
    - 哈希表:{1 -> 节点1, 2 -> 节点2}
  3. get(1):访问键 1。
    - 通过哈希表查找键 1 对应的节点,并将其移到链表头部,表示最近使用。
    - 链表:[1, 2](1是最新的,2是次新的)
    - 哈希表:{1 -> 节点1, 2 -> 节点2}
  4. put(3, 3):插入键值对 (3, 3)。因为缓存满了,删除最久未使用的键 2。
    - 链表:[3, 1](3是最新的,1是次新的)
    - 哈希表:{1 -> 节点1, 3 -> 节点3}

如果没有哈希表,在 get(1) 操作时,你需要遍历整个链表来找到键 1。而引入哈希表后,可以在 O(1) 时间内直接定位到键 1 对应的节点,大幅提升查找效率。

代码实现

14、一个线程池应该包含什么?

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

一个线程池在实现时,通常需要包含以下几个关键组成部分:
在这里插入图片描述

线程池的一个简单示例代码:

#include <iostream>
#include <vector>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <future>class ThreadPool {
public:ThreadPool(size_t threads);~ThreadPool();template<class F, class... Args>auto enqueue(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type>;private:// 工作线程std::vector<std::thread> workers;// 任务队列std::queue<std::function<void()>> tasks;// 同步std::mutex queue_mutex;std::condition_variable condition;bool stop;
};// 构造函数,创建线程池
ThreadPool::ThreadPool(size_t threads) : stop(false) {for (size_t i = 0; i < threads; ++i) {workers.emplace_back([this] {for (;;) {std::function<void()> task;{std::unique_lock<std::mutex> lock(this->queue_mutex);this->condition.wait(lock, [this]{ return this->stop || !this->tasks.empty(); });if (this->stop && this->tasks.empty()) return;task = std::move(this->tasks.front());this->tasks.pop();}task();}});}
}// 添加任务到线程池中
template<class F, class... Args>
auto ThreadPool::enqueue(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type> {using return_type = typename std::result_of<F(Args...)>::type;auto task = std::make_shared<std::packaged_task<return_type()>>(std::bind(std::forward<F>(f), std::forward<Args>(args)...));std::future<return_type> res = task->get_future();{std::unique_lock<std::mutex> lock(queue_mutex);if (stop) {throw std::runtime_error("enqueue on stopped ThreadPool");}tasks.emplace([task](){ (*task)(); });}condition.notify_one();return res;
}// 析构函数,销毁线程池
ThreadPool::~ThreadPool() {{std::unique_lock<std::mutex> lock(queue_mutex);stop = true;}condition.notify_all();for (std::thread &worker : workers) {worker.join();}
}int main() {ThreadPool pool(4);auto result1 = pool.enqueue([](int answer) { return answer; }, 42);auto result2 = pool.enqueue([](int a, int b) { return a + b; }, 10, 20);std::cout << "Result 1: " << result1.get() << std::endl;std::cout << "Result 2: " << result2.get() << std::endl;return 0;
}

之后我会持续更新,如果喜欢我的文章,请记得一键三连哦,点赞关注收藏,你的每一个赞每一份关注每一次收藏都将是我前进路上的无限动力 !!!↖(▔▽▔)↗感谢支持!

http://www.dtcms.com/a/360039.html

相关文章:

  • MongoDB 从零到入门:实用指南
  • 多租户配额与预算:限额、配额周期与突发桶的结算模型(Final)
  • juicefs+ceph rgw 存储安装
  • React 状态管理演进之路:从 Dva 到现代架构
  • leetcode 面试题 01.01.判定字符是否唯一
  • 解决浏览器的**混合内容安全策略**(Mixed Content Security Policy)带来的无法访问页面
  • 深入探讨JavaScript性能瓶颈:我的优化实战与思考
  • PBR 、 IPv6 PBR(基于策略的路由)原理与配置
  • 《济公》电视剧总结学习
  • 家庭全光组网高温故障深度分析与散热重构全记录
  • linux系统之----共享内存
  • 开学季,音频格式古诗词,也可作为启蒙教育。
  • C#异步编程
  • OpenCL C++ 内核(Kernel)
  • 【动态规划】回文串问题
  • linux修改权限命令chmod
  • 借助 Kubernetes 与 vLLM 实现大规模大语言模型推理
  • 使用Cadence工具完成数模混合设计流程简介
  • uvm do on
  • 【深度学习】配分函数:近似最大似然与替代准则
  • Python毕业设计推荐:基于Django+MySQL的养老社区服务管理系统
  • Spring —— 数据源配置和注解开发
  • 【IDE问题篇】新电脑安装Keil5,出现找不到arm 编译器版本5编译报错;改为版本6后旧代码编译是出现编译报错
  • 通过编辑Offer Letter源代码实现批量修改
  • 刚上线的PHP项目被攻击了怎么办
  • Java全栈开发面试实战:从基础到微服务的全面解析
  • 策略模式:模拟八路军的抗日策略
  • 【Java后端】SpringBoot配置多个环境(开发、测试、生产)
  • LangChain框架深度解析:定位、架构、设计逻辑与优化方向
  • Mysql什么时候建临时表