- 博客(49)
- 收藏
- 关注
原创 二分查找算法
本文系统介绍了二分查找算法的原理与应用。首先阐述了二分查找的核心思想——利用数组的二段性进行高效搜索,并详细讲解了三种模板:朴素二分、查找左边界和查找右边界模板。随后通过8道经典题目(704、34、69、35、852、162、153、LCR173)展示了二分查找的具体应用,包括有序数组查找、峰值检测、旋转数组最小值等问题。文章强调二分查找的关键在于发现问题的二段性,并提供了详细的代码实现和边界条件处理技巧。每种题型都分析了算法原理、二段性特点以及指针移动策略,为理解和应用二分查找提供了全面指导。
2025-12-07 16:05:05
747
原创 滑动窗口算法
本文总结了8道滑动窗口相关的算法题解,涵盖长度最小子数组、无重复字符子串、最大连续1个数、将x减到0、水果成篮、字母异位词和最小覆盖子串等问题。每道题都详细分析了暴力解法与滑动窗口优化思路,重点讲解了如何利用双指针同向移动的特性,通过进窗口、判断、出窗口和更新结果四个步骤高效解决问题。文章提供了清晰的示例解析、时间复杂度分析和代码实现,特别强调了如何利用单调性和哈希表来优化算法性能。这些题目展示了滑动窗口在解决连续子数组/子串问题中的强大应用。
2025-12-05 15:22:29
1001
原创 双指针算法
本文介绍了利用双指针算法解决数组问题的多个经典案例。双指针通过移动数组下标来高效处理数据,主要分为三种应用场景:1.移动零问题(283题)使用快慢指针分区处理;2.快乐数问题(202题)通过快慢指针检测循环;3.多数和问题(三数之和15题、四数之和18题等)采用排序后固定基准值结合双指针搜索。文章详细分析了每道题的解题思路、边界条件处理和时间复杂度,并提供了C++代码实现。双指针算法能有效降低暴力解法的时间复杂度,是处理数组类问题的常用优化手段。
2025-12-03 20:57:25
994
原创 手动封装系统调用实现缓冲区
本文介绍了如何实现一个简单的文件I/O库,封装了文件操作的基本功能。通过定义myFILE结构体来管理文件描述符、缓冲区和刷新模式,实现了myfopen、myfclose、myfputs和myfflush等核心函数。其中重点实现了三种缓冲区刷新策略:行缓冲、全缓冲和无缓冲,并处理了强制刷新和尝试刷新的不同场景。通过Makefile组织项目结构,分为头文件、实现文件和测试文件,最终验证了缓冲区的正确工作方式。该实现展示了C语言标准库中文件操作函数如何封装系统调用,并实现缓冲机制来提高I/O效率。
2025-12-01 18:53:13
878
原创 文件IO的底层原理:从系统调用到缓冲区管理
本文探讨了Linux系统中文件操作的核心概念。首先分析了文件的基本组成(文件内容+属性)和访问方式(通过路径+文件名)。重点阐述了进程与文件的关系,指出文件操作本质是进程通过CPU访问内存中的文件。文章详细介绍了文件描述符的分配规则和重定向原理,解释了标准输入/输出/错误的底层实现。同时深入剖析了缓冲区的层级结构(语言级缓冲区和内核级缓冲区)及其刷新策略,揭示了系统调用与库函数的封装关系。最后讨论了"一切皆文件"的设计哲学,展示了Linux如何通过统一的文件接口管理各类资源。
2025-11-30 17:45:06
1013
原创 进程控制三板斧:创建、等待、终止
本文系统介绍了Linux进程管理的核心概念和操作。首先详细讲解了fork函数的用法、失败原因及写时拷贝机制,重点阐述了进程终止的三种情况(正常结束、结果错误、异常终止)及其判断方法。随后深入探讨了进程等待的必要性,对比分析了wait和waitpid函数的阻塞与非阻塞等待方式。最后详细介绍了程序替换的原理及7种exec函数族的使用方法,包括参数传递和环境变量处理。文章通过大量示例代码演示了父子进程创建、多进程管理、程序替换等核心操作,为深入理解Linux进程管理提供了全面指导。
2025-11-24 17:48:09
642
原创 聊聊Linux中的“进程”到底是什么?
本文深入探讨了进程的概念、管理及虚拟地址空间。首先定义了进程为运行中的程序,其核心是内核数据结构与代码数据的结合。随后详细讲解了进程控制块(PCB)的作用,包括状态、优先级、内存指针等属性。接着分析了Linux系统中进程的7种状态及其转换条件,并通过fork函数演示父子进程创建和资源管理机制。文章还介绍了进程优先级调度算法和命令行参数与环境变量的应用。最后深入解析了虚拟地址空间的原理,包括区域划分、页表映射机制及其保护内存和实现进程独立性的作用。
2025-11-20 17:29:01
853
原创 我的创作纪念日
摘要 本文记录了作者从计算机专业学生到优快云博客创作者的成长历程。最初为记录编程学习笔记而开始写博客,逐渐将博客视为知识梳理和复习的工具。作者保持纯粹的学习态度,不以流量和点赞为目标,坚持免费分享知识。博客创作与学习进度同步,帮助加深对知识的理解。展望未来,作者希望尽快获得实习机会,在IT行业找到立足之地,并承诺继续保持博客的免费开放。全文展现了学生技术博主的学习路径与成长思考。
2025-11-16 17:52:01
165
原创 计算机的“身体”与“灵魂”:冯·诺依曼架构与操作系统
摘要:冯诺依曼体系结构定义了计算机的基本组成和工作原理,包括输入、计算、输出三个核心环节。该体系通过引入内存作为缓冲,解决了CPU与外设速度不匹配的问题,提高了整体效率。内存的存在使计算机在性价比上取得平衡,促进了计算机的普及和互联网的发展。操作系统作为资源管理软件,通过描述和组织软硬件资源进行管理,并为用户提供系统调用接口。所有访问硬件的操作都必须通过操作系统,而外壳程序、开发库和指令都是基于系统调用构建的不同功能层。
2025-11-08 14:37:15
447
原创 调试界的“双屏神器”:CGDB如何让你边看代码边调试?
本文介绍了使用cgdb调试工具的基本方法与技巧。cgdb在gdb基础上增加可视化代码窗口,调试更直观。主要内容包括:1) 安装gdb/cgdb的方法;2) 通过示例程序说明debug与release版本的区别,需添加-g选项生成调试信息;3) 详细讲解cgdb常用命令:断点设置(b)、变量查看(p/display)、单步执行(n/s)、条件断点等;4) 对比cgdb与gdb的操作差异,如上屏代码窗口与下屏命令窗口切换(ESC/i键)。cgdb通过可视化界面和丰富的调试命令,能有效提升代码调试效率。
2025-11-04 20:34:53
994
原创 你的第一个 Linux 系统程序:从进度条开始
本文详细介绍了在Linux系统中实现进度条程序的过程。首先讲解了回车(\r)和换行(\n)的区别及其在C语言中的使用方式,通过缓冲区刷新机制(fiflush)解决了打印延迟问题。然后逐步实现了一个完整的进度条功能,包括进度显示、百分比计算和旋转光标效果。文章还探讨了进度条的实际应用场景,如文件下载时的网络速度浮动处理,并通过函数指针实现了模块化设计。最后介绍了如何为进度条添加彩色输出效果。整个过程涵盖了Makefile构建、缓冲区管理、格式化输出等关键技术点,展示了Linux系统编程的实用技巧。
2025-11-02 14:30:41
1000
原创 告别手动编译:用Makefile自动化你的Linux项目
摘要:本文介绍了Make和Makefile的基本概念与使用方法。Makefile定义了项目构建规则,通过依赖关系和依赖方法实现自动化编译,解决了多源文件管理的复杂性问题。文章详细阐述了Makefile的基本语法结构、依赖关系原理、伪目标(.PHONY)的作用,以及如何使用变量优化Makefile编写。同时讲解了文件时间戳对编译过程的影响,并给出了处理多个源文件的Makefile编写技巧,包括通配符和模式规则的使用。最后展示了如何编写一个通用的Makefile,可灵活应用于C/C++项目,提高开发效率。
2025-11-01 11:12:04
1080
原创 深入浅出GCC:Linux下的C/C++编译利器
本文介绍了Linux系统下gcc/g++编译器的使用。gcc用于编译C语言,g++用于编译C++和C语言,但建议分开使用。文章详细讲解了程序编译的四个过程:预处理(去注释、宏替换、头文件展开)、编译(检查语法并转汇编)、汇编(生成二进制文件)、链接(关联库函数)。重点分析了动态链接和静态链接的区别:动态链接节省内存但依赖库文件,静态链接独立但体积大。默认使用动态链接,可通过-static选项强制静态链接。通过示例演示了如何使用不同选项观察各编译阶段的结果,并解释了编译器自举的概念。
2025-10-30 17:35:08
955
原创 深入浅出哈希表
本文深入解析了C++11新增的unordered_set和unordered_map容器及其底层哈希表实现。主要内容包括:两种容器的声明差异(需要支持转换为整型和比较相等)、迭代器特性(双向vs单向)、性能比较(O(1)平均复杂度优于红黑树的O(logN))。重点讲解了哈希表的核心概念:哈希函数设计(除留余数法为主)、解决冲突方法(开放定址法和更优的链地址法),并提供了两种方法的完整代码实现,包含扩容策略(素数表扩容)、字符串特例处理等关键细节。通过性能测试数据对比,证实了哈希容器在多数场景下的高效性。
2025-10-29 11:22:04
762
原创 红黑树的色彩魔法:红与黑背后的平衡艺术
红黑树是一种自平衡二叉搜索树,通过颜色约束规则确保近似平衡。相比AVL树,红黑树对平衡的控制更宽松,插入时旋转次数更少。红黑树遵循四点规则:根节点黑色、红色节点子节点必须黑色、任意路径黑色节点数相同。插入新节点时通过变色和旋转(左旋/右旋)维持平衡,主要处理父节点和叔节点的颜色情况。红黑树保证了最长路径不超过最短路径的两倍,查找、插入、删除操作的时间复杂度均为O(logN)。检查红黑树平衡需验证四条规则,包括根节点颜色、连续红色节点和路径黑节点数等。
2025-10-25 19:38:22
1029
原创 C++实现AVL树:理解旋转操作的每一个细节
AVL树是一种自平衡二叉搜索树,通过平衡因子(右子树高度减左子树高度)确保每个节点的左右子树高度差不超过1。文章详细介绍了AVL树的结构、插入操作及平衡因子更新规则,重点讲解了四种旋转操作(左单旋、右单旋、左右双旋、右左双旋)的实现细节,包括指针调整和平衡因子更新。最后给出了检查AVL树是否平衡的方法,通过递归计算子树高度差进行验证。AVL树的平衡性保证了其查找、插入、删除等操作的时间复杂度为O(logN)。
2025-10-24 14:48:49
823
原创 容器适配器、关联容器的相关算法题目
题目分析:设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。top和getMin操作总是在上调用pushpoptop, andgetMin最多被调用3 * 104次由题目所描述的“能在常数时间内检索到最小元素的栈”,说明时间复杂度为O(1)。“poptop和getMin操作总是在非空栈上调用”说明在执行 pop,top,getMin 操作时,不需要考虑栈为空的情况。--> 返回 -3.--> 返回 0.--> 返回 -2.算法思路。
2025-10-22 18:24:09
841
原创 深入理解STL关联容器:map/multimap与set/multiset全解析
本文介绍了STL中的关联式容器set、multiset、map和multimap。主要内容包括:set和map的特点和使用方法,如set的排序去重特性、map的键值对存储结构;容器常用接口如insert、erase、find、count等的功能和使用场景;重点解析了map的operator[]操作符的底层实现原理及其多功能特性;最后对比了set/multiset和map/multimap在支持数据冗余方面的差异。文章通过大量代码示例展示了这些容器的具体应用,如统计词频、遍历修改等场景。
2025-10-21 21:59:22
862
原创 C++容器适配器深度解析:stack/queue/priority_queue的设计哲学
本文介绍了C++中的三种容器适配器:stack(栈)、queue(队列)和priority_queue(优先队列)。stack和queue分别基于后进先出(LIFO)和先进先出(FIFO)原则,默认使用deque作为底层容器;priority_queue基于堆结构,默认使用vector作为底层容器。文章详细阐述了它们的实现原理、接口函数及模拟实现方法,并比较了不同容器的优缺点。此外,还深入探讨了deque(双端队列)的内部结构及其作为适配器底层容器的优势,最后介绍了仿函数在容器适配器中的应用。
2025-10-19 15:01:24
781
原创 二叉搜索树的原理、实现与性能分析
【摘要】二叉搜索树是一种特殊的二叉树结构,左子树节点值均小于等于根节点,右子树节点值均大于等于根节点。文章详细介绍了二叉搜索树的基本性质、时间复杂度(最优O(logN),最差O(N))、插入/查找/删除操作的实现方法,以及key/value二叉搜索树的扩展应用。重点讲解了删除操作的四种情况处理,特别是左右孩子都不为空时的替换法删除策略,并提供了完整的C++代码实现。最后展示了key/value二叉搜索树在统计词频中的实际应用案例。该结构是map/set等STL容器的基础实现方式。
2025-10-17 09:32:13
664
原创 多态:C++面向对象编程的“灵魂”所在
文章摘要:本文深入探讨了C++中多态的实现原理。多态分为编译时多态(函数重载)和运行时多态(虚函数机制)。重点分析了运行时多态的两个必要条件:基类指针/引用调用虚函数,以及派生类必须重写虚函数。通过实例演示了虚函数表的工作机制,解释了虚函数指针如何实现动态绑定。文章还详细讨论了虚函数重写的特殊情况(如协变、析构函数重写)、override和final关键字的使用,以及纯虚函数和抽象类的关系。最后通过内存分析验证了虚函数表存储在只读数据段的特性。
2025-10-14 21:54:45
668
原创 Effective C++:关于继承,你需要知道的几件事
面向对象程序设计的三大特性分别为:封装,继承,多态。使用继承可以定义相似的类型并对其相似关系建模。继承机制是面向对象程序设计使代码可以复用的最重要的手段,它允许我们在保持原有类特性的基础上进行扩展,增加方法(成员函数)和属性(成员变量)。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的函数层次的复用,继承是类设计层次的复用。继承public:{}{}private:// 姓名// 地址// 电话int m_age;
2025-10-12 17:46:32
802
原创 为什么你的代码总是重复?是时候了解模板了
C++模板是泛型编程的基础,分为函数模板和类模板。函数模板通过参数类型生成特定函数,避免重复编码;类模板则创建通用类结构。模板支持隐式和显式实例化,并能特化处理特殊类型。模板声明和定义通常放在同一文件中以避免链接问题。虽然模板提高了代码复用性和灵活性,但也可能导致代码膨胀和复杂错误信息。文章详细介绍了模板的定义、使用、特化及编译分离问题,并分析了其优缺点。
2025-10-09 17:17:18
980
原创 vim 入门与精要:从零到熟练
之前我们编写,编译,调试,运行代码都是在VS2022上一并完成的,这种从代码编写,编译到调试,运行,将所有功能都集成在一款工具上的工具称之为IDE(集成开发工具)。Linux中的开发工具不是 IDE,而是一个个独立的工具:写代码的工具为:编辑器 vim,vi(vi 是很老的编辑器)编译代码的工具为:gcc,g++调试的工具为:gdb,cgdb构建工具为:makefile,make,cmake,git本篇博客主要关于编辑器 vim 的使用,vim 是一个只用来写代码的工具。
2025-09-27 22:19:12
1166
原创 Linux --- 软件包管理器
在 windows 系统中可以安装软件,那么在 linux 系统里是否可以安装软件呢?当然可以。在Linux下安装软件,⼀个通常的办法是下载到程序的源代码,并进行编译,得到可执行程序。但是这样太麻烦了,于是有些人把⼀些常用的软件提前编译好,做成软件包(可以理解成 windows 上的安装程序)放在一个服务器上,通过包管理器可以很方便的获取到这个编译好的软件包,直接进行安装。在linux系统中安装软件的常见方式:1. 源代码安装基本步骤:1. 获取源代码;2. 解压源代码包;3. 配置编译选项;
2025-09-26 19:14:13
528
原创 STL容器 --- 模拟实现 list
如这般将 const _list_iterator<T> 重命名为 const_iterator,这样就变成本身不能被修改,反而指向的内容可以被修改,这样迭代器就不能++了,这样如何迭代?在实现 push_back 函数时,新建结点,将 val 传给 list_node 类中的构造函数,接下来就来实现该函数,参数给全缺省值,那么缺省值是什么?迭代器实现完毕后,在 list 中实现迭代器相关的函数:普通版本迭代器的 begin 和 end 函数,const 版本迭代器的 begin 和 end 函数。
2025-09-21 21:36:48
748
原创 STL 容器 --- list 类
list 中使用的函数与之前所学的,并无太多的区别,下面只简单的讲解一些特殊的地方。List 是链表,是之前数据结构所说的带头双向循环链表,使用 list 时需要包含头文件 --- list。原型为:。
2025-09-21 10:56:54
975
原创 Linux --- 权限
文件属性的最开头有十个字符,第一个字符表示的是文件的具体类型,剩下的9个字符,每3个为一组,分别表示拥有者权限,所属组权限,other权限。如何正确的表达一个文件的权限:分别列举拥有者,所属组,other有什么权限,如上图中 test.txt文件的权限表达为:拥有者ww 拥有可读,可写权限,没有可执行权限;sudoers 文件是超级管理员的权限,任何人是没有办法直接访问这个文件的,只有存在于 /etc/sudoers 文件的可信任用户列表中的用户才能执行 sudo 指令,这个文件是由管理员管理的。
2025-09-16 21:58:33
1119
原创 Linux --- 常见的基本指令
本篇博客使用的 Linux 操作系统是 centos ,用来学习Linux 的 Linux 系统的内核版本和系统架构信息版本如下所示:上图的主要结构为:主版本号-次版本号 修正次数,3.10.0 是操作系统的主版本号;当我们在维护一段Linux源代码时,它的修正次数足够多时,次版本号就会递增一次;当次版本号修正足够多时,主版本号就会递增一次。当次版本号为偶数时,代表着这是稳定版本;当次版本号为奇数时,代表着这是测试版本。
2025-09-13 15:54:33
393
原创 C++ —— STL容器 —— vector的模拟实现
相较于 string ,vector 相当于一个简洁版的 string ,它们两个容器的函数的功能都一致,只是在函数参数上略有差异。尽管如此,vector 还是存在一些自身的特点,这些会在模拟实现的同时一一介绍;vector 的许多函数的实现都与 string 差不多,所以实现起来会更简单。
2025-06-24 19:17:09
1053
原创 C++ —— STL容器 —— string的模拟实现
了解 string 的各个常用的接口之后,可以尝试模拟实现 string 类。模拟实现string 类并不是为了实现一个与库中一样的 string ,而是为了让我们更好的了解 string 类的底层,在之后使用 string 类出现错误时,能快速的找到问题,并解决问题,同时能够加深对 C++ 知识的掌握。这里的模拟实现函数的声明与定义分离。在模拟实现的过程中,为了避免命名冲突的问题,三个文件中都可以使用关键字 namespace。
2025-06-13 21:34:03
1174
1
原创 C++ —— STL容器——string类
本篇博客将会介绍 string 中的一些常用的函数,在使用 string 中的函数时,需要加上头文件string。
2025-06-01 21:15:05
1283
原创 面向对象编程基石:类与对象完全解析
本文详细解析了C++中类和对象的核心概念。类通过访问限定符(public/private/protected)控制成员的可访问性,成员变量通常设为私有,成员函数设为公有。类实例化对象时仅分配成员变量空间,不存储成员函数指针,成员函数存放在代码段。类的大小仅由成员变量决定,遵循内存对齐规则。文章还对比了class和struct的区别,并演示了内联成员函数的特性,全面阐述了面向对象编程的基础知识。
2025-05-07 20:13:40
1038
原创 深度解析C语言四大自定义类型:结构体、联合、枚举与位段
C语言中的自定义类型——结构体详解 本文介绍了C语言中自定义类型结构体的基本概念和使用方法。主要内容包括: 结构体的声明语法和成员变量的定义方式 结构体变量的定义、初始化和成员访问方法 匿名结构体的特殊声明和限制 结构体自引用在链表等数据结构中的应用 结构体内存对齐规则及其对结构体大小的影响 通过示例代码详细展示了结构体的各种操作,包括嵌套结构体的使用、成员修改和内存对齐原理。结构体作为一种重要的自定义数据类型,能够有效解决复杂对象的表示问题,在数据结构中具有广泛应用价值。
2025-05-03 19:28:16
1125
原创 C语言排序算法的底层逻辑与性能对比
本文介绍了两种常见的排序算法:插入排序(包括直接插入排序和希尔排序)和选择排序(直接选择排序)。直接插入排序通过逐个插入有序序列实现排序,时间复杂度为O(N^2);希尔排序使用增量分组策略改进插入排序,时间复杂度约为O(N^1.3)。选择排序通过每次选择最小/最大值进行交换来实现排序。文章详细说明了各算法的实现步骤、代码示例和时间复杂度分析,并通过示例展示了排序前后的数据变化。
2025-04-23 16:44:27
1010
原创 指针与递归的共舞:C语言链式二叉树精讲
本文介绍了链式结构二叉树的实现及其四种遍历方式。二叉树结点包含数据域和左右孩子指针,通过递归方式创建二叉树。前序遍历顺序为根-左-右,中序遍历为左-根-右,后序遍历为左-右-根。文中详细分析了每种遍历的递归过程,并给出了示例代码和运行结果。二叉树的链式结构相比堆限制较少,主要通过递归实现遍历操作而非插入删除。这些遍历方式是二叉树基础操作的核心内容。
2025-04-13 21:21:45
1163
原创 顺序结构二叉树:数组与树的“二象性”
本文介绍了树和二叉树的基本概念及存储结构。树是一种非线性数据结构,由根节点和多棵互不相交的子树组成,具有层次性。二叉树是树的一种特殊形式,每个节点最多有两个子节点,且子树有左右之分。文章详细讲解了树的相关术语(如度、深度、路径等)和二叉树的特点,包括满二叉树和完全二叉树的定义及区别。最后介绍了用顺序结构实现二叉树(堆)的方法,包括堆的结构定义、初始化、销毁和插入数据等操作,指出顺序存储更适合完全二叉树以避免空间浪费。
2025-04-12 19:10:56
1096
原创 经典面试题精讲:C语言实现随机链表的复制(附最优解)
本文探讨了循环队列的设计与实现方法。循环队列是一种首尾相连的环形结构,具有固定空间、队头删除、队尾插入等特点。文章比较了链表和数组两种实现方式,指出数组实现更节省内存且简单。重点分析了数组实现时的关键问题:如何区分队列空和满状态。解决方案是通过多开辟一个空间,利用(rear+1)%(k+1)==front判断满状态,而front==rear表示空状态。文章提供了完整的代码实现框架,包括结构体定义、初始化、插入删除操作及判断空满状态的方法。这种实现方式避免了额外计数器变量的使用,提高了空间效率。
2025-04-11 22:03:51
1189
原创 C语言中的“叠盘子”与“排队伍”:栈与队列深入浅出
本文介绍了栈的基本概念和实现方法。栈是一种后进先出(LIFO)的线性表,只能在固定端(栈顶)进行插入和删除操作。文章对比了数组和链表两种实现方式,指出数组更适合作为栈的底层结构,因其内存消耗更小且时间复杂度更低(O(1))。详细讲解了栈的结构定义、初始化、入栈、出栈、取栈顶元素等基本操作的具体实现,并分析了各种操作的性能要求。最后还介绍了获取栈中有效数据个数和销毁栈的方法。通过代码示例展示了栈的基本操作过程,包括空间扩容机制和边界条件处理。
2025-04-08 12:09:06
997
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅