- 博客(26)
- 收藏
- 关注
原创 红黑树(Red-Black Tree)实现原理详解
红黑树是一种近似平衡的二叉搜索树,通过颜色约束(根黑、红结不连续、路径黑数相同)保证最长路径不超过最短2倍。插入时新节点初始为红,通过变色和旋转(单旋/双旋)调整平衡,时间复杂度保持O(logN)。相比AVL树,红黑树旋转次数更少,广泛应用于C++ STL、Java集合和Linux内核等场景。其核心实现包括节点颜色标记、插入规则处理(分三种情况)和旋转操作,确保在动态更新中维持近似平衡特性。
2026-06-02 10:59:05
225
原创 AVL树详解与实现(C++)
AVL树是一种自平衡二叉搜索树,通过平衡因子(左右子树高度差不超过1)确保高效查找。插入节点时需先按二叉搜索树规则插入,再更新平衡因子。当平衡因子超过±1时,通过四种旋转(右单旋、左单旋、左右双旋、右左双旋)恢复平衡。旋转操作能降低子树高度并保持平衡,确保树的高度始终为O(log n)。具体旋转类型的选择取决于插入位置导致的子树不平衡情况。
2026-05-27 19:06:53
457
原创 STL关联式容器:map 与 set 的使用
STL容器分为序列式容器(如vector、list)和关联式容器(如set、map)。序列式容器按顺序存储数据,支持位置访问;关联式容器基于键值组织数据,通常使用红黑树实现,查找效率为O(logN)。set自动去重排序,map存储key-value对且key唯一。multiset/multimap允许重复元素。map支持[]操作符访问元素,set/map常用操作包括插入、查找、删除和遍历。关联式容器通过lower_bound/upper_bound实现范围查询,迭代器操作需注意失效问题。
2026-05-26 19:53:05
369
原创 二叉搜索树(BST)详解
二叉搜索树(BST)是一种特殊的二叉树结构,具有左子树节点值小于根节点、右子树节点值大于根节点的特性。其优势在于高效的查找、插入和删除操作,时间复杂度最优可达O(logN),但最坏情况下会退化为链表结构(O(N))。BST的中序遍历结果必然有序,插入和查找操作遵循比较规则,而删除操作最为复杂,需处理四种不同情况(叶子节点、单子树节点、双子树节点)。BST可分为key型和key/value型,分别对应set和map的应用场景。相比二分查找,BST在插入删除效率上更优且无需连续存储空间,但稳定性较差,后续可通过
2026-05-22 21:07:48
386
原创 C++ 多态详解(Polymorphism)
摘要:C++多态分为编译时多态(函数重载/模板)和运行时多态(虚函数)。实现运行时多态需满足:通过基类指针/引用调用虚函数,且派生类完成虚函数重写。虚函数重写要求函数名、参数、返回值相同,但默认参数值不参与重写。建议将基类析构函数声明为虚函数以避免内存泄漏。C++11引入override检查重写正确性,final禁止继续重写。纯虚函数(=0)使类成为抽象类,不可实例化且派生类必须重写。虚函数通过虚表实现动态绑定,每个含虚函数的类都有虚表,同类型对象共享虚表,派生类覆盖虚表中的函数地址。
2026-05-20 15:27:42
357
原创 C++继承详解
本文系统介绍了C++继承机制的核心概念与应用。主要内容包括:继承的基本语法(父类定义、子类派生)、三种继承方式(public/protected/private)及其访问规则,重点分析了public继承的is-a关系。详细讲解了继承中的构造函数、拷贝构造、赋值运算符和析构函数的调用顺序与实现要点,以及作用域隐藏、静态成员处理等特性。针对菱形继承问题,介绍了虚继承解决方案。最后对比了继承(is-a)与组合(has-a)的适用场景,建议优先使用组合以降低耦合度。全文通过代码示例阐释了继承体系中的关键技术和最佳实
2026-05-19 20:23:27
440
原创 C++模板进阶
C++模板进阶:非类型参数与特化技巧 本文深入探讨C++模板的两个高级特性:非类型模板参数和模板特化。非类型参数允许使用编译期常量作为模板参数,但需注意必须是整型/枚举类型且为常量表达式。模板特化分为函数特化和类特化,后者又包含全特化和偏特化,用于处理特定类型的特殊需求。文章通过日期类比较等实例,展示了指针特化的实际应用,并分析了模板分离编译问题的根源及解决方案(推荐将声明定义统一放在.hpp文件中)。这些技巧能有效提升模板的灵活性和适用性,但需谨慎使用以避免复杂性。
2026-05-19 12:03:56
380
原创 STL——stack、queue 与 priority_queue 详解
本文介绍了STL中的三种容器适配器:stack、queue和priority_queue。stack是后进先出(LIFO)结构,queue是先进先出(FIFO)结构,priority_queue本质是堆结构。文章详细说明了它们的概念、常用接口函数及基本使用方法,并展示了如何用vector和list分别模拟实现stack和queue。此外,还介绍了双端队列deque的特点、优缺点,以及priority_queue的大小堆实现方式。这些容器适配器通过封装底层容器提供特定功能,是STL中重要的数据结构组件。
2026-05-18 17:48:31
380
原创 C++ STL——list 容器详解
摘要:C++ STL中的list是一个基于双向循环链表的序列容器,擅长频繁插入删除操作。其特点包括任意位置高效插入删除,但随机访问效率低。list提供多种构造方式,使用双向迭代器访问元素。主要操作包括push/pop_front/back、insert、erase等,并内置sort排序功能。与vector不同,list不支持随机访问迭代器操作,因此不能直接使用算法库的sort函数,而是通过成员函数sort实现排序。
2026-05-18 12:01:55
374
原创 C++ STL容器--vector详解
本文系统介绍了C++ STL中的vector容器。主要内容包括:vector是动态顺序表,支持随机访问和动态扩容;详细讲解了构造方式(无参、拷贝、迭代器区间等)、迭代器遍历方法(begin/end、范围for)和容量操作(size/resize/reserve);分析了VS和g++下的不同扩容机制(1.5倍vs 2倍);列举了增删查改常用接口(push_back/insert/erase等);重点阐述了迭代器失效问题及其解决方案;最后介绍了二维vector的定义和使用。文章强调reserve预扩容可提高效率
2026-05-15 18:51:52
451
原创 C++SLT-string类详解
摘要:本文详细介绍了C++标准库中的string类,包括其基本特性、常用构造函数、容量操作、访问遍历方式以及修改操作。string类能自动管理内存并支持动态扩容,提供多种构造方式(无参、带参、拷贝等)和实用接口(size、empty、clear等)。文章还讲解了四种遍历方法([]操作符、迭代器、范围for、auto关键字)以及常用修改操作(push_back、append、find等)。最后介绍了getline函数读取整行输入的方法,解决了cin遇到空格停止的问题。
2026-05-13 20:51:46
396
原创 C++模板初阶
本文介绍了C++中的泛型编程与模板机制。主要内容包括:1)泛型编程概念,通过模板实现代码复用;2)函数模板的定义与使用方式,编译器根据参数类型自动生成具体函数;3)模板实例化的两种方式(隐式和显式);4)模板与普通函数的匹配规则;5)类模板的定义与实例化方法;6)模板代码通常需要放在头文件中的原因。模板机制将重复编码工作交给编译器,提高了代码的通用性和可维护性,是C++实现泛型编程的核心技术。
2026-05-11 16:12:10
360
原创 C++内存管理(超详细解析)
本文系统讲解了C/C++程序的内存分布与动态内存管理机制。首先介绍了程序内存的四大区域:栈(局部变量)、堆(动态内存)、数据段(全局/静态变量)和代码段(常量)。重点分析了不同变量在内存中的存储位置,包括全局变量、静态变量、局部变量和动态分配的内存。详细对比了C语言的malloc/calloc/realloc/free与C++的new/delete操作,指出后者会自动调用构造/析构函数且支持初始化。特别强调了new/delete必须配对使用,并解释了new失败时的异常处理机制。最后揭示了new/delete
2026-05-11 13:54:53
446
原创 C++拷贝构造函数详解(深度解析)
C++拷贝构造函数详解:拷贝构造函数是C++中用于对象复制的重要特殊构造函数,其标准形式为类名(const类名&)。关键特性包括:必须使用引用参数以避免无限递归,默认情况下编译器会生成执行浅拷贝的版本。浅拷贝适用于简单数据类型(如Date类),但对于包含指针和动态内存的类(如Stack类)必须实现深拷贝,即重新分配内存并复制内容。拷贝构造与赋值运算符的区别在于前者用于初始化新对象,后者用于已有对象间的赋值。在函数返回值处理上,传值返回会调用拷贝构造,而引用返回可避免拷贝但需注意不能返回局部变量引用。
2026-05-10 21:19:58
403
原创 归并排序详解
归并排序是一种基于分治思想的稳定排序算法,通过不断拆分数组为最小单元后有序合并实现排序。其核心步骤包括:递归地将数组二分至单个元素(天然有序),然后两两归并有序区间。算法需要O(n)辅助空间存储临时数组,时间复杂度稳定为O(nlogn)。实现方式可分为递归(思路清晰但有调用开销)和非递归(无递归但边界处理复杂)两种,关键点在于处理归并时的数组越界问题。归并排序的稳定性来源于合并时优先取左区间元素,保持相同元素的原始顺序。
2026-05-09 21:50:32
377
原创 C++六大默认成员函数之二--构造函数与析构函数详解
本文介绍了C++中类的默认成员函数,重点讲解了构造函数和析构函数。构造函数负责对象初始化而非创建对象,具有自动调用、可重载等特性;析构函数负责资源清理而非销毁对象,生命周期结束时自动调用。文章还讨论了this指针、默认构造函数的行为、C++11缺省值、空类大小等问题,并阐述了RAII思想(资源获取即初始化)这一C++核心资源管理机制。通过对比C语言的初始化方式,展示了C++自动调用构造和析构函数的优势,有效降低了资源泄漏风险。
2026-05-09 21:34:50
409
原创 C++引用(Reference)详解——从入门到理解本质
C++引用详解摘要:引用是变量的别名,与原变量共享内存空间,本质上是同一对象的多个名称。关键特性包括必须初始化、不能重新绑定、允许多个引用指向同一对象。引用主要用于简化传参(替代指针)、提高效率、修改结构体和作为返回值。const引用用于处理常对象和临时对象。与指针相比,引用更安全易用但不能为空或改变绑定。引用在数据结构和函数参数传递中广泛应用,能有效替代二级指针,提升代码可读性。引用不是新变量,而是原变量的另一个名称。
2026-05-08 21:20:15
348
原创 计数排序详解
计数排序是一种非比较型整数排序算法,通过统计元素出现次数实现排序。其核心思想是空间换时间,采用绝对映射或相对映射(推荐)将数值转换为数组下标,能处理负数并节省空间。实现步骤包括:确定数值范围、创建计数数组、统计频率、恢复有序数组。时间复杂度为O(n+range),空间复杂度O(range)。优点是速度快、实现简单,适合数据范围集中的整数排序;缺点是需要额外空间,不适用于小数或离散数据。典型应用包括成绩统计、年龄排序等场景。
2026-05-08 10:37:24
374
原创 希尔排序详解
小的元素大致靠前大的元素大致靠后中间元素分布相对合理前半部分整体较小后半部分整体较大那么它就比完全逆序更接近有序状态。通过 gap 分组不断优化数据结构,使插入排序在接近有序的数据上运行。
2026-05-07 13:40:00
311
原创 直接插入排序算法详解
直接插入排序是一种非常直观的排序方式,它的思想和我们日常生活中的“整理扑克牌”过程非常相似。其核心思路是:将数据分为“已排序部分”和“未排序部分”,每次从未排序部分取一个元素,插入到已排序序列中的合适位置,从而逐步扩大有序区间。刚开始时,第一个元素天然是有序的,之后不断“插入新元素”,最终完成整体排序。实现简单稳定排序算法适用于小规模数据数据量大时效率较低(O(n²))
2026-05-06 18:23:23
446
原创 快速排序详解
本文系统介绍了快速排序算法的实现与优化。主要内容包括:1. 三种实现方式(左右交换法、挖坑法、前后指针法)的原理与代码实现;2. 时间复杂度分析(最优O(NlogN),最坏O(N²))及优化策略(三数取中、小区间优化);3. 非递归实现方法,通过栈结构替代递归调用。文章通过图示和代码示例详细讲解了每种方法的执行过程,并针对递归可能导致的栈溢出问题提出了非递归解决方案,为快速排序的实际应用提供了全面的技术指导。
2026-05-06 16:59:30
383
原创 【数据结构】--二叉树
二叉树是一种非线性的树形数据结构,它要么为空,要么由一个根节点以及互不相交的左、右子树构成,每个节点最多拥有两个子节点,且严格区分左孩子与右孩子,左右子树次序固定,具备递归的结构特点。如上图所示为二叉树的逻辑结构而物理结构上,二叉树可以是顺序式的,也可以是链式的。
2026-04-28 17:49:09
392
原创 【数据结构】-双向链表
链表可分为带哨兵卫头节点和不带头节点的,单链表或者双向链表,循环或者不循环的,这3种方式可以组成8种链表,其中,最常见的是不带头节点的单向不循环链表和带头节点的双向循环链表。之前对于无哨兵卫头节点的单链表,我们传的都是2级指针,所以有小伙伴不能理解,是不是因为带头节点就可以传2级指针,而不带头节点的就穿二级指针呢?在单链表的基础上,我们再加一个prev指针,让该节点既能找到下一节点,也能找到上一个节点,这样的链表我们称为双向链表。大致思路也是一样的,先修改前后节点的指针,然后再释放该节点。
2026-04-23 16:59:43
159
原创 数据结构-单链表
这里有2种插入数据的方式,区别是指定位置之前插入数据多传了一个参数**pphead,这是因为,该方式下,pos节点被删除后,要把pos前节点的next指针指向pos的next,而要找到pos前节点,需要根据头节点来遍历找到,同时要注意细节问题,当插入位置为头节点时,此时prev已经在头节点同时也是pos,prev->next永远不可能为pos,所以要单独判断。我们定义单链表时,创立了一个链表的指针,并赋值为NULL,如果我们传一级指针,就会出现链表插入失败的情况,下面是我画的一个简图。
2026-04-22 17:07:20
170
原创 【数据结构】顺序表
此外在插入数据时一定要检查空间是否足够,不够要进行增容,增容我们一般用realloc函数,并且增容的大小也是有讲究的,一般我们进行倍数增容,通常为2-3倍。就是先把数据进行挪动,把要插入的位置空出来,再进行该位置的插入,而删除只需要进行数据覆盖就行,然后时数据查找,遍历该顺序表就行,查找到返回下标,否则返回-1。显然由于静态的空间大小已经定死,后期如果在数据已满的情况下,无法再增添新的数据,所以动态的顺序表更有优势,下面是动态顺序表的定义。头插也是一样的,先检查空间大小,然后插入数据,
2026-04-20 15:14:59
39
原创 C++命名空间(namespace)的基本使用
在C++中,命名空间(namespace)是用来组织代码和避免命名冲突的一种机制。随着项目的复杂度增加,命名空间的使用可以极大地提高代码的可维护性和可扩展性。本篇博客将深入探讨命名空间的基本概念、语法和实际应用,并结合常见的命名冲突问题,展示如何利用命名空间来优化代码结构。命名空间是C++中非常强大的工具,可以帮助我们有效地避免命名冲突,组织代码结构。在学习和使用命名空间时,我们应注意合理组织命名空间,避免滥用using指令,以保证代码的可维护性。
2025-01-18 23:48:27
457
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅