- 博客(87)
- 收藏
- 关注
原创 [C++高阶数据结构] LRU Cache 的两张表,为什么必须互相存对方的位置?
LRU缓存通过哈希表与双向链表结合实现O(1)时间复杂度。哈希表存储键到链表迭代器的映射,快速定位;链表按访问顺序维护节点,头部为最近使用,尾部为最久未用。get操作命中则将节点移至头部,未命中返回-1;put操作更新或插入节点,容量满时淘汰尾部节点。关键技巧包括:链表节点存key以支持反查删除、使用splice移动节点避免迭代器失效、双容器协同保证高效性。
2026-10-31 10:11:55
27
原创 [Linux信号篇] 按下 Ctrl+C 到进程死掉,中间发生了什么?
按下 Ctrl+C 时,键盘并不直接杀死进程,而是触发终端向当前前台进程组发送 SIGINT 信号。进程收到信号后,根据其处理方式决定是否退出。信号是异步通知,由内核通过修改进程的“未决”(pending)和“屏蔽”(block)表来实现。标准信号不排队,因它们仅用位图记录,无法区分重复次数。信号来源多样:终端按键、系统调用、硬件异常或定时器。无论来源如何,内核统一通过“写信号”机制更新进程状态。最终,只有前台进程组能接收键盘输入,因此被杀的是与用户交互的程序。
2026-10-28 23:24:16
288
3
原创 [动态规划子数组] 为什么四道 DP 题,我栽在了同一个地方?
四道动态规划题均因状态定义不当导致复杂度飙升或逻辑错误。核心问题在于:状态表示不完整,信息未充分压缩进状态,迫使转移时反复回溯或分类讨论。如等差数列题中,应以“结尾”为状态,避免遍历前缀;湍流子数组需分离“上升/下降”方向;单词拆分应以“位置”为单位而非“字符串”;环绕字符串则需用26维数组去重。教训是:定状态后先试推转移,若复杂即止损,优先保证状态能支持简洁转移。
2026-10-27 20:19:42
219
4
原创 学习技术的改进方案:如何从学完走向真正的学会?
我曾沉迷于生产结论,却忽视了推理过程。从记笔记、刷算法到写博客,本质都是“战术勤奋,战略懒惰”。真正的问题在于:只记结论,不追因果。通过重构学习流程——聚焦卡点、反直觉、条件代价、转折逻辑,用口述复盘、白纸推演、分段检验,我开始训练底层思维。博客不再堆砌代码,而是以“现象-我以为-其实是-所以”四步构建因果链,让知识真正内化。改变的不是方法,而是对“理解”的定义:唯有生产推理,才能摆脱学生思维,走向真正的成长。
2026-10-24 00:11:10
257
原创 [Linux系统] 进程间通信 | 匿名管道 | 基于匿名管道模拟实现进程池
进程间因地址空间独立,无法直接共享数据,故需通信以实现数据传输、资源共享、事件通知与进程控制。管道作为最基础的IPC机制,通过内核缓冲区实现父子进程间半双工、流式通信,依赖fork复制文件描述符实现共享。其特点包括:仅限有共同祖先的进程、无消息边界、生命周期随进程、内核自动同步。结合匿名管道可模拟进程池,预先创建子进程等待任务指令,提升任务处理效率,避免频繁创建销毁进程的开销。
2026-10-22 23:58:35
749
5
原创 [动态规划#1] 子数组 | 最大子数组和 | 环形子数组的最大和 | 乘积最大子数组 | 乘积为正数的最长子数组
本文系统讲解子数组问题的动态规划解法,核心思想是“以当前位置结尾”分类枚举。通过状态表示(如最大和、最小和、正负乘积长度)、状态转移(分类讨论)与初始化,实现O(N)时间复杂度。涵盖最大子数组和、环形子数组最大和、乘积最大子数组及乘积为正的最长子数组四类经典题型,强调开多表处理符号变化、下标映射与返回值特殊判断等关键技巧。
2026-10-22 17:50:23
59
原创 [优选算法#20] BFS拓扑排序 | 课程表 | 课程表 II | 火星词典
本文介绍基于BFS的拓扑排序算法,用于解决课程表、火星词典等依赖关系问题。核心思想:将任务建模为有向图,通过维护入度数组和队列实现拓扑排序,判断是否存在环。应用包括判断课程能否完成(207题)、生成学习顺序(210题),以及从字典序单词推导字母大小关系(火星词典)。关键点:正确建图方向、去重边、处理前缀冲突边界情况。时间复杂度均为 $O(N + M)$,空间复杂度 $O(N + M)$。
2026-10-20 22:47:24
274
1
原创 [C++高阶数据结构] 图的定义 | 邻接矩阵 | 邻接表 | 图的遍历方式
图是由顶点集与边集构成的数据结构,记作 $ G = (V, E) $。与树不同,图可有环、不连通,且两点间路径不唯一。分为无向图与有向图,区别在于边的方向性,影响度、连通性及矩阵对称性。完全图边数分别为 $ \frac{n(n-1)}{2} $(无向)和 $ n(n-1) $(有向)。存储结构上,邻接矩阵适合稠密图,支持快速判断连通性,但空间复杂度高;邻接表更适合稀疏图,便于遍历邻接点,节省空间。
2026-10-20 20:07:08
468
2
原创 [C++高阶数据结构] 并查集原理 | 模拟实现 | 力扣算法题实战
并查集用于维护不相交集合,支持查找根节点、合并集合及统计集合数量。通过数组实现,负数表示根节点(绝对值为集合大小),非负数表示父节点。优化包括路径压缩和小树合并大树,提升效率。典型应用如“省份数量”和“等式可满足性”,通过遍历关系建立并查集,最终统计连通分量数或验证约束一致性。
2026-10-19 18:00:26
262
3
原创 [Linux系统] 动静态库的制作与使用 | ELF加载 | 动静态链接全流程
库是可复用的二进制代码,分为静态库(.a/.lib)和动态库(.so/.dll)。静态库在链接时合并至可执行文件,运行无需依赖;动态库在加载时按需载入,支持多进程共享,节省内存。ELF 文件通过节头表(链接视角)与程序头表(执行视角)组织代码,链接将多个 .o 文件的 section 合并为 segment。静态链接完成编译重定位,动态链接则通过 GOT 表实现运行时重定位,并支持延迟绑定优化。关键区别在于:静态链接体积大但独立,动态链接省空间但依赖运行环境。
2026-10-16 21:29:13
65
3
原创 [版本控制器Git] Git 远程仓库 | 多人协作 | 企业级 Git Flow 开发模型
Git 是分布式的,每人本地都是完整版本库,远程服务器只为交换修改。克隆分两种协议:HTTPS 免配置但要输密码,SSH 需把 `id_rsa.pub` 加到平台公钥。本地与远端靠 push/pull 同步,push 失败就先 pull,冲突解决并 commit 后再推送。同一分支上走 push-pull-push,或一一人一个 feature 分支互不干扰;接手他人分支需先建立跟踪关系,合并前让本地分支先吸收 master;企业级开发
2026-10-14 19:42:19
1573
原创 [版本控制器Git] Git 版本控制 | 三区模型与版本回退 | 分支管理
本文系统介绍了Git的核心原理与操作:作为主流版本控制器,Git通过工作区、暂存区、版本库三区管理文件变更,利用SHA1哈希实现对象存储与内容追踪。重点讲解了add与commit的边界、reset三兄弟回退策略、reflog恢复误删、分支合并冲突处理及stash暂存现场等实战技巧,强调“提交需显式add”、“撤销分阶段处理”、“合并建议禁用fast-forward保留历史”,帮助开发者高效协作与安全回溯。
2026-10-13 21:04:32
1538
4
原创 [Linux系统] 磁盘 | Ext2 文件系统 | 块、分区和inode | 目录与挂载 | 软硬链接
文件系统核心:磁盘以LBA为逻辑地址,按块(4KB)组织;文件 = 内容(数据块)+ 属性(inode),inode存储元信息并指向数据块。ext2通过块组划分分区,包含超级块、GDT、位图、inode表与数据区。目录本质是“文件名→inode号”映射,路径解析从根目录逐级查找,dentry缓存加速访问。挂载将分区关联到目录树,实现跨分区访问。硬链接共享inode,软链接为独立文件指针。
2026-10-10 21:53:34
54111
2
原创 [Linux系统] 一切皆文件 | 缓冲区机制 | FILE 结构
Linux的“一切皆文件”源于内核用struct file和file_operations实现统一接口,使设备如磁盘、管道、socket均可通过read/write操作。缓冲区由C标准库提供,分全、行、无缓冲三类,用于协调高速CPU与低速外设。printf等库函数有用户级缓冲,重定向后需fflush才落盘;fork时写时拷贝导致未刷新数据重复输出,而write无缓冲故仅一次。核心:FILE封装fd与缓冲区,实现高效I/O。
2026-09-30 19:28:13
6333
原创 [Linux系统] 基础IO核心 | 系统接口 | 文件描述符 | 重定向
文件操作本质依赖系统调用,fopen/fread仅为libc封装。文件描述符是files_struct数组下标,按“最小未使用”规则分配。重定向通过dup2改变fd指向,实现输出/输入流切换。一切皆文件,核心在于内核通过file_operations统一设备访问接口。
2026-09-28 16:25:51
3101
原创 [Linux系统] 进程程序替换:exec系列函数详解
exec 系列函数的核心作用是将新程序加载到当前进程地址空间,替换原有代码与数据,从新程序的启动例程执行,实现“换脑子”而不创建新进程。其本质为进程内部的程序替换,进程ID不变,成功时不返回,失败需立即 exit兜底。六个函数由 l/v(参数形式)、p(PATH搜索)、e(自定义环境)组合而成,仅 execve 为系统调用,其余均为库函数封装。典型用法为 fork + exec + wait,模拟 Shell 执行命令的完整流程,如 ls、ps 等外部命令均通过此机制运行。
2026-09-27 17:40:59
23579
原创 [Linux系统] 进程创建 | 进程终止 | 进程等待
本文系统讲解进程管理核心机制:fork实现写时拷贝的进程创建,父子通过返回值分流执行;进程终止使用exit(刷新缓冲)或_exit(立即退出),退出码通过$?查看;waitpid用于回收子进程资源,防止僵尸进程,支持阻塞与非阻塞等待,通过status位图获取退出状态。三者构成进程生命周期完整闭环。
2026-09-26 18:04:30
25933
原创 [Linux系统] 命令行参数 | 环境变量 | 程序地址空间
本文系统阐述了C程序中的三大核心机制:命令行参数(argc、argv)实现程序行为多样化;环境变量(如PATH、HOME)提供全局运行配置,需通过export传递给子进程;程序地址空间基于虚拟内存,由mm_struct与vm_area_struct管理,通过页表映射实现内存保护、解耦与高效管理。三者共同支撑进程的独立性与安全性。
2026-09-24 17:45:55
6038
原创 [Linux系统] 进程优先级 | 进程切换 | 内核进程O(1)调度队列
本文详解Linux进程调度机制:优先级由PRI与nice决定,nice越小优先级越高;进程切换本质是CPU寄存器上下文的保存与恢复,由时间片耗尽触发;O(1)调度算法通过活动/过期队列、位图加速查找,实现常数时间复杂度调度,确保高效响应。
2026-09-23 17:17:14
50783
原创 [Linux系统] 冯诺依曼体系 | 操作系统 | 进程状态
本文系统阐述了冯诺依曼体系结构下计算机硬件与软件的协同机制,重点解析操作系统在软硬件资源管理中的核心作用。通过进程与PCB(task_struct)概念,揭示进程的生命周期与状态管理,涵盖进程创建(fork)、状态转换(运行、睡眠、僵尸等)及资源回收机制。结合实例说明系统调用、写时拷贝、cwd与exe特性,并剖析僵尸进程与孤儿进程的成因与处理方式,全面展现操作系统对进程的精细化管控。
2026-09-22 19:49:03
7946
原创 [Linux系统] 版本控制器Git | 调试器gdb/cgdb的使用
本文聚焦开发效率核心工具:Git与gdb/cgdb。Git通过add/commit/push三板斧实现代码版本管理,解决文件混乱与协作难题;gdb配合-g编译选项提供精准调试能力,结合cgdb实现可视化分屏调试。进阶技巧如watch监视、set var修改变量值、条件断点等,显著提升问题定位效率。掌握这些工具链,是高效编程的基石。
2026-09-21 15:28:28
12044
原创 [Linux系统] 自动化构建make / Makefile | 进度条
本文介绍了Makefile与make命令的协同机制,实现项目自动化构建,解决手动编译繁琐问题。通过依赖关系、依赖方法和伪目标(.PHONY)确保高效编译与清理。结合依赖推导与变量扩展语法,提升构建灵活性。同时演示了基于\r回车符的进度条实现原理,利用fflush(stdout)刷新输出,动态显示下载/上传进度,展现高效交互式界面设计。
2026-09-20 23:14:05
1121
原创 [Linux系统] 编辑器vim、编译器和动静态链接
本文系统介绍Linux下C/C++开发核心工具:vim编辑器的三种模式及常用命令,gcc/g++编译流程(预处理、编译、汇编、链接)与关键选项,以及动态库(.so)与静态库(.a)的链接差异。通过实例演示编译过程与链接方式对比,阐明动态链接节省资源但依赖库,静态链接独立运行但体积大。内容涵盖从环境配置到实际编译调试的完整链路,助力高效开发。
2026-09-19 23:31:12
2661
原创 [C++] 拷贝构造还是赋值重载?类默认成员函数细节详解
C++98中类的默认成员函数包括构造、析构、拷贝构造与赋值重载,用于资源管理与对象复制。C++11新增移动语义,提升效率。析构函数负责清理资源,遵循后定义先析构原则;拷贝构造与赋值需深拷贝避免资源重复释放;运算符重载支持对象像变量般操作,注意避免自赋值与浅拷贝问题。现代写法推荐传值+swap实现高效赋值。
2026-09-17 17:48:13
1729
原创 [C++] C++11智能指针:如何避免内存泄漏?
RAII(资源获取即初始化)通过对象生命周期管理资源,有效防止内存泄漏。智能指针(如unique_ptr、shared_ptr)遵循RAII原则,支持异常安全:在抛出异常时自动释放资源。unique_ptr不支持拷贝,避免悬空;shared_ptr基于引用计数,但存在循环引用问题,需配合weak_ptr解决。标准库智能指针位于<memory>,支持自定义删除器、make_shared高效构造及operator bool判断空指针,提升代码安全性与可读性。
2026-09-16 20:20:04
995
原创 [C++] C++11异常从抛出到捕获全解析
C++11引入异常机制,通过throw抛出对象、catch捕获并处理错误,实现更精准的错误定位。异常按调用链查找,匹配最近的catch,未找到则终止程序。推荐引用捕获避免拷贝开销,基类catch可捕获派生类异常,catch(...)用于兜底。示例中模拟服务器系统,通过继承体系实现多类型异常处理,支持异常重新抛出与重试逻辑,提升程序健壮性。
2026-09-15 20:11:27
1256
原创 [C++] C++11 Lambda与包装器深度解析
本文系统介绍了C++中lambda表达式与std::function、std::bind包装器的语法与应用。lambda作为匿名函数,支持捕捉外部变量(传值/传引用),可配合mutable修改捕获的副本;其底层为仿函数对象。std::function统一封装各类可调用对象,实现类型无关调用;std::bind则用于调整参数数量与顺序,增强函数适配灵活性。二者结合可简化代码逻辑,提升可读性与复用性,广泛应用于算法、线程及回调场景。
2026-09-14 19:52:45
1188
原创 [C++] C++11类和STL的新特性
C++11引入多项新特性:默认生成移动构造/赋值,支持default与delete控制函数生成;final禁止继承或重写,override确保正确重写;成员变量可在声明时初始化。STL新增unordered_set/map等无序容器,支持右值引用、移动语义、emplace插入及范围遍历,提升性能与代码简洁性。
2026-09-13 19:12:23
1505
原创 [C++] C++11可变参数模板揭秘:从原理到emplace
C++11引入可变参数模板,支持函数与模板的参数包(Args...),通过sizeof...获取参数数量。包展开分为递归与并列两种方式:递归需外部终止函数,而并列展开利用GetArgs(args)...实现统一处理。emplace系列接口基于完美转发,支持直接构造并插入元素,避免拷贝开销,高效处理左值、右值及多参数构造,广泛应用于容器如vector、unordered_map中。
2026-09-12 16:27:11
1733
原创 [C++] C++11右值引用与移动语义揭秘
本文系统阐述了C++中左值、右值及其引用的概念,重点介绍左值引用与右值引用的区别与应用。通过参数匹配机制,右值引用可实现移动语义,避免深拷贝开销。结合移动构造与移动赋值,显著提升传值返回和传参效率,是解决资源管理问题的标准方案。
2026-09-11 21:07:25
860
原创 [C++] C++11新增构造:列表初始化和std::initializer_list
C++11引入列表初始化,支持所有对象用{}直接初始化,避免拷贝开销,提升效率。配合std::initializer_list,可实现任意数量元素的初始化,广泛用于容器和自定义类型。两者区别在于:列表初始化参数个数固定(由类型决定),而std::initializer_list支持任意个数,底层通过数组存储并提供迭代器访问。
2026-09-10 17:52:09
1069
原创 [C++] 揭秘函数调用背后的栈帧真相
未初始化的局部变量值随机,甚至显示为“烫”,是因为调试模式下栈空间被初始化为0xCC,连续两个0xCC在GBK编码中恰为“烫”。形参修改不影响实参,因传参本质是将实参值复制到栈上,形参仅为副本,函数返回后栈帧销毁,实参不受影响。这一切都源于函数调用时的栈帧机制:参数压栈、栈帧创建与销毁,确保了函数调用的独立性与安全性。
2026-09-09 22:13:13
695
原创 [C++] 泛型哈希表设计:从零封装unordered_set与unordered_map
本文介绍C++11的unordered_set与unordered_map,底层为哈希桶,增删查改平均O(1)。与set/map相比,要求key可转整型并支持相等比较,迭代器单向,遍历无序。二者复用同一HashTable封装,通过仿函数提取key,map额外支持operator[]。
2026-09-08 21:06:00
8824
原创 [C++] 哈希表:从原理剖析到模拟实现
哈希是一种通过哈希函数将关键字映射到存储位置、支持O(1)查找的思想。哈希冲突不可避免,可用负载因子衡量冲突概率。减少冲突可优化哈希函数与扩容。处理冲突常用开放定址法和链地址法,后者即哈希桶,是STL采用的主流方案。
2026-09-06 20:54:51
14220
原创 [C++] 深入理解红黑树:封装set与map
本文基于GCC源码分析set和map共用红黑树模板,通过仿函数提取key,适配不同容器;模拟实现迭代器、插入查找及map的operator[],重点阐述中序遍历下迭代器增减的节点跳转逻辑,实现代码复用。
2026-09-05 12:07:40
15098
原创 [LC优选算法#19] 前缀和 | 连续数组 | 矩阵区域和
这篇文章主要讲解了LeetCode中两道关于前缀和应用的题目: 连续数组:寻找包含相同数量0和1的最长子数组。通过将0视为-1转化为求和为0的子数组问题,利用哈希表记录前缀和及其首次出现的位置,实现O(N)时间复杂度的解法。 矩阵区域和:计算矩阵中每个元素周围k×k区域的元素和。通过构建二维前缀和数组,快速计算任意矩形区域的和,解决了多次查询矩阵子区域和的问题。关键点在于正确处理边界条件和坐标转换。 两题都展示了前缀和技巧在处理区间/区域求和问题中的高效性,分别适用于一维和二维场景。
2026-07-08 15:50:47
57996
3
原创 [LC优选算法#18] 前缀和 | 除⾃⾝以外数组的乘积 | 和为K的⼦数组 | 和可被K整除的⼦数组
本文介绍了三个基于前缀和思想的算法题解: 除自身以外数组的乘积:通过左右前缀数组预处理,将结果拆分为左右两部分乘积,避免除法并实现O(N)时间复杂度。 和为K的子数组:利用前缀和配合哈希表,将问题转化为查找sum[i]-k的出现次数,优化至O(N)时间。 和可被K整除的子数组:结合同余定理与负数取模修正,通过哈希表统计同余前缀和的数量,同样达到O(N)效率。 核心思想均为通过前缀和预处理数据,结合哈希表优化查找过程,将暴力解法的O(N²)复杂度降至线性。
2026-07-06 14:26:08
257
2
原创 [LC优选算法#17] 链表 | 合并 K 个升序链表 | K个⼀组翻转链表
本文介绍了两种链表问题的解法:1) 合并K个升序链表:可采用暴力法(O(NK^2))、小根堆优化(O(NKlogK))或分治递归法(O(NK*logK)),其中堆和分治法通过高效比较节点值来优化性能;2) K个一组翻转链表:通过模拟头插法实现分组翻转,需计算组数并处理剩余节点。两种问题均给出了C++代码实现,强调算法选择对性能的影响。
2026-07-05 13:43:08
204
1
原创 [LC优选算法#16] 链表 | 两数相加 | 两两交换链表中的节点 | 重排链表
本文总结了链表操作的常用技巧和典型例题。主要技巧包括:画图模拟指针操作、使用虚拟头节点简化边界处理、快慢双指针应用等。通过三个LeetCode例题展示了具体应用:1)两数相加通过模拟进位过程实现;2)两两交换节点时需注意指针更新顺序;3)重排链表采用找中点、反转、合并的三步策略。文章强调链表操作中指针处理的精确性和画图的重要性,并提供了C++代码实现。这些方法能有效解决链表类算法问题。
2026-07-03 15:37:11
265
1
原创 [LC优选算法#15] 前缀和 | 一维前缀和 | 二维前缀和 | 寻找数组的中心下标
本文介绍了前缀和算法及其应用场景。前缀和通过预处理数组构建累积和序列,实现区间和的快速查询,是典型的空间换时间思想。文章分析了一维和二维前缀和的实现方法:一维前缀和通过差值计算区间和;二维前缀和采用容斥原理计算子矩阵和。通过三个例题展示具体应用:一维区间和查询、二维矩阵区域和查询以及寻找数组中心下标问题。前缀和算法能将暴力解法的O(N*Q)时间复杂度优化至O(N+Q),显著提高查询效率。代码实现中需注意边界处理,如二维前缀和的行列偏移设置。
2026-07-02 16:09:33
250
13
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅