- 博客(70)
- 收藏
- 关注
原创 模拟实现 unordered_map 与 unordered_set — 基于哈希桶的泛型复用
T _data;// 存储 K 或 pair<const K, V>
2026-11-07 17:16:52
411
18
原创 哈希表(Hash Table)从概念到手写实现
哈希表的三大支柱哈希函数:决定"散得开不开"——除法散列 + 质数 M 是性价比最高的选择。负载因子:决定"何时扩容"——超过阈值必须 Rehash,否则性能骤降。冲突解决:决定"挤在一起怎么办"——开放定址"表内让位",链地址"表外挂链"。🔑 最后的心法:哈希表是概率 + 工程的产物。理论上的"O(1) 查找"依赖于均匀散列 + 冲突受控两个前提。真正的高性能哈希表,永远在**"更少的冲突"与"更少的内存"之间**寻找那个平衡点——而这一切的起点,就是本科题目里那个看似朴素的除留余数法。
2026-11-06 15:30:22
753
18
原创 模拟实现 map 和 set —— 基于红黑树的复用设计
/ 三叉链,便于迭代器 -- / ++ 向上回溯T _data;Color _col;, _data(data), _col(RED) // 新结点默认红色{}设计决策目的收益模板参数T而非K, V让同一棵树同时容纳K和pair<K,V>一次实现,两处复用KeyOfT仿函数从T中抽出真正的 key 进行比较map 只以 key 排序,符合语义迭代器用nullptr表示 end结合"向祖先回溯"的++逻辑无需额外标记位,天然对齐Insert返回同时告知位置与是否新插。
2026-11-04 17:01:07
494
15
原创 红黑树:从概念到实现
情况叔叔u操作是否继续上推1存在且红pu变黑,g变红是,把g当新c2黑或不存在,且同向单旋 +p黑、g红否3黑或不存在,且异向双旋 +c黑、g红否主题关键结论平衡方式黑高一致 + 无连续红,保证最长路径不超过最短路径 2 倍插入颜色空树插黑;非空树插红父黑直接结束父红叔红只变色,g当新c继续上推父红叔黑/不存在,同向单旋 +p黑、g红父红叔黑/不存在,异向双旋 +c黑、g红根最后必须染黑查找与普通 BST 相同验证。
2026-11-01 15:59:13
457
17
原创 map和set的使用
set是一个关联容器,用于存储唯一且有序的元素。class set;Key:表示集合中元素的类型,即关键字类型。Compare:比较函数对象,默认为less<Key>,要求支持操作符或可调用的仿函数,用于确定元素之间的顺序。Allocator:内存分配器,默认使用标准分配器。⚠️关键点set要求元素类型Key必须支持“小于”比较(即a < b成立),否则无法构建红黑树结构。若需自定义排序规则(如降序、字符串忽略大小写等),可通过自定义仿函数传入Compare参数。底层实现为。
2026-10-28 16:40:54
499
25
原创 搜索二叉树
特性说明✅ 结构特性左 ≤ 根 ≤ 右,递归定义✅ 插入从根出发,按大小方向走,直到空位插入✅ 查找逐层比较,最多走高度次✅ 删除四种情况,双子树用“替换法”✅ 时间复杂度最好OlogNO(\log N)OlogN,最坏ONO(N)ON✅ 应用场景仅 key → 集合;key/value → 映射表✅ 限制不支持修改 key,否则破坏结构✅ 升级方案用 AVL / 红黑树解决不平衡问题🚀最终建议在实际工程中,不要直接使用原始二叉搜索树。
2026-10-24 17:57:50
493
26
原创 c++多态
多态是⼀个继承关系的下的类对象,去调⽤同⼀函数,产⽣了不同的⾏为。关键字作用推荐场景override显式声明函数意图重写基类虚函数所有派生类中希望重写的虚函数final禁止该虚函数被后续派生类重写设计为“终结者”的接口或关键逻辑💡建议在所有重写函数前加上override,提高代码健壮性。对于不想被继承重写的函数,使用final明确语义。结合两者使用可构建更安全、易维护的继承体系。📌颜色强调说明红色:表示编译错误或不可接受的行为(如错误重写、违反 final 限制)。绿色:表示正确使用。
2026-10-11 19:18:26
475
34
原创 数据结构队列
顺序队列的⼀个经典问题就是假溢出问题,队列的存储空间(数组)中明明还有空闲位置,但由于队尾指针rear已经移动到了数组的末尾,导致⽆法再插⼊新元素,系统错误地判断为“队列已满”的现象,这种情况之所以被称为“假”溢出,是因为它并⾮真正的空间耗尽,⽽是⼀种由于数据结构设计缺陷导致的空间浪费。队列的链式存储,我们可以选⽤单链表结构,也可以选⽤双向链表结构。顺序存储结构实现队列,⼊队对应尾插,出队对应头删,⽽顺序存储结构直接头删的需要挪动数据时间复杂度为 O(n),如果实现队列的顺序存储结构效率太低,就⽆价值了。
2026-10-05 18:40:49
432
10
原创 数据结构栈
/ 栈的初始化// 栈的销毁// 元素入栈(进栈)// 元素出栈,并返回栈顶元素// 获取栈顶元素(不删除)// 获取栈中有效元素个数// 判断栈是否为空这些接口构成了栈功能完整性的基础,所有实现都围绕这组操作展开。} LSNode;// 指向栈顶节点(即链表头)int size;// 当前栈中元素个数核心思想:后进先出(LIFO),限制操作位置提升效率。首选实现方式动态顺序栈,兼顾性能与实用性。典型应用场景函数调用栈(运行时堆栈)
2026-10-04 20:07:34
348
21
原创 c++继承
继承是面向对象编程中实现代码复用的重要机制。通过继承,一个类(派生类)可以获取另一个类(基类)的成员(数据和函数),并在此基础上扩展或修改功能。在 C++ 中,派生类通过class 派生类名 : 继承方式 基类名 {// 派生类新增的成员继承方式可以是publicprotected或private。默认情况下,class定义的类默认继承方式为privatestruct为public。基类private成员在任何继承方式下都不可见,即使被继承也受语法限制。
2026-10-03 19:34:01
609
17
原创 c++模板进阶
非类型模板参数(Non-type Template Parameters)是C++模板机制中一种特殊的参数形式,允许开发者将常量值直接作为模板的一部分进行传递。与类型形参(如class T或typename T)不同,非类型形参传递的是具体的值,而非类型信息。这类参数在编译期必须能够确定其值,因此只能接受那些在编译时即可计算出结果的表达式。这使得非类型模板参数特别适用于需要静态配置的场景,例如数组大小、循环次数、位宽等。非类型模板参数用于传递编译期常量值。支持类型:整数、枚举、指针、引用、
2026-10-02 19:04:27
563
15
原创 priority_queue的介绍和使用
默认情况下,优先队列是大根堆(即堆顶为最大值)。若需实现小根堆(堆顶为最小值),可通过自定义比较函数进行配置。其中是一个模板仿函数,表示“较小者优先”,从而使得队列顶部始终为最小元素。更复杂的自定义比较逻辑也可通过定义结构体或函数对象实现,灵活适应不同应用场景。优先队列是基于堆结构的容器适配器,提供高效的最大/最小元素访问;默认使用作为底层容器,支持随机访问与动态扩展;所有堆操作均由内部算法自动完成,用户无需关心具体实现细节;核心操作如push()pop()top()
2026-10-01 19:52:44
595
16
原创 stack和queue(类函数学习和模拟实现)
stack的文档介绍stack是一种后进先出(LIFO, Last In First Out)的容器适配器,属于标准模板库(STL)中的一种。它仅允许在栈顶进行插入和删除操作,保证了数据访问的顺序性。stack底层通常由dequelist或vector实现,具体取决于编译器实现,但用户无需关心底层细节。只能通过top()访问栈顶元素。元素只能从栈顶压入(push)或弹出(pop不支持随机访问或遍历。适用于递归模拟、表达式求值、括号匹配、函数调用栈等场景。queue的文档介绍queue。
2026-09-30 19:11:04
495
19
原创 List(模拟实现)
iterator:允许修改元素内容;:只读访问,用于const容器。特性说明价值哨兵节点_head自环,空链表时消除边界判断,统一逻辑双向循环链表支持前后移动,O(1)插删高效支持任意位置操作模板参数复用迭代器X/Y控制返回类型一份代码支持iterator与inserterase复用所有增删操作基于这两个核心函数降低耦合,减少错误现代赋值运算符按值传参 +swap异常安全,简洁高效erase返回next解决迭代器失效问题支持clear()的安全循环删除本实现充分体现了现代 C++
2026-09-24 10:35:01
311
22
原创 List(类函数学习)
特性说明✅ 高效插入/删除任意位置插入删除均为 O(1)✅ 迭代器安全(除被删节点外)其他迭代器不受影响❌ 不支持随机访问无法使用lst[i]❌ 内存开销大每个节点额外存储前后指针⚠️ 适合场景频繁增删、需要保持顺序、不需要随机访问实现队列、栈(结合push_frontpop_front动态维护有序集合(如任务调度)需要频繁在中间插入/删除的数据结构。
2026-09-20 16:34:10
735
18
原创 带头双向循环链表实现
/ 存放实际数据// 指向前驱节点// 指向后继节点data:存储用户定义的数据类型,可灵活替换为字符串、结构体等;prve:关键字段,使我们能够“回溯”到前一个节点;next:保持原有单链表的正向连接能力。值得注意的是,这里的prve是拼写错误(应为prev),建议修正为prev以提高代码可读性和规范性。尽管不影响逻辑运行,但良好的命名习惯有助于团队协作与后期维护。任意位置插入/删除均可 O(1) 完成;不再区分“头”与“尾”,统一处理;空链表状态清晰,无需特殊判断;
2026-09-18 16:36:51
263
20
原创 vector(模拟实现)
亮点说明✅不使用 memcpy保证对等类类型的深拷贝,杜绝内存错误✅copy-and-swap 惯用法赋值运算符简洁、异常安全、自动处理自赋值✅插入时重定位迭代器扩容后重新计算pos偏移量,避免迭代器失效✅erase 返回迭代器符合 STL 规范,支持安全删除循环✅均摊 O(1) 插入2 倍扩容策略,降低频繁分配成本✅支持任意迭代器构造可从arraylistset等构造vector✅RAII 内存管理所有资源由对象自身管理,无泄漏风险理解vector避免踩坑(如迭代器失效、浅拷贝崩溃);
2026-09-15 17:00:56
410
17
原创 vector(类函数学习)
构造函数声明接口说明vector()默认构造函数,创建一个空的 vector,size = 0,capacity = 0构造并初始化n个元素,每个元素值为val拷贝构造函数,复制另一个 vector 的所有元素使用迭代器范围初始化 vector// 1. 默认构造// 2. 指定大小和初始值// 3. 拷贝构造// 复制 v2 内容// 4. 迭代器初始化// C++11 范围初始化// 输出验证return 0;✅重点提示vector()
2026-09-14 16:37:23
447
16
原创 string(模拟实现)
资源管理 = 构造 + 拷贝 + 交换 + 析构”机制作用构造函数分配资源,初始化状态拷贝构造深拷贝,保障独立性swap快速转移资源所有权析构函数释放资源,防止泄漏使用拷贝-交换惯用法实现赋值。采用RAII原则管理动态内存。优先使用优化内存操作。保持接口一致性和异常安全性。
2026-09-13 16:18:59
520
16
原创 string(类函数学习)
string类的文档介绍代码说明:代码说明:范围for对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因此C++11中引入了基于范围的for循环。for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围,自动迭代,自动取数据,自动判断结束。范围for可以作用到数组和容器对象上进行遍历。范围for的底层很简单,容器遍历实际就是替换为迭代器,这个从汇编层也可以看到。使用引用()可以修改容器中的元素,使用值()则只
2026-09-12 14:26:39
350
20
原创 c++模板初阶
核心思想:类模板与函数模板类似,将「数据类型」作为参数传递给类,让同一份类代码能够处理多种不同类型的数据,从而避免为每种类型重复编写几乎相同的类。定义格式:在类定义之前加上(或),类中所有需要「类型可变」的成员位置都用模板参数T来占位。// 类模板:可以存储任意类型的数据public:// 用 T 来分配数组空间~Stack()void Push(const T& val) // 用 T 作为参数类型T Pop() // 用 T 作为返回值类型private:T* _data;
2026-09-08 16:00:47
436
16
原创 c++内存管理
int main()// new/delete 和 malloc/free最大区别是 new/delete对于【自定义类型】除了开空间还会调用构造函数和析构函数free(p1);delete p2;//最好// 内置类型是几乎是一样的// Cfree(p3);delete p4;free(p5);return 0;
2026-09-07 16:14:44
553
17
原创 Cplusplus入门
定义命名空间,需要使⽤到namespace关键字,后⾯跟命名空间的名字,然后接⼀对{}即可,{}中即为命名空间的成员。命名空间中可以定义变量/函数/类型等。namespace本质是定义出⼀个域,这个域跟全局域各⾃独⽴,不同的域可以定义同名变量。C++中域有函数局部域、全局域、命名空间域、类域;域影响的是编译时语法查找⼀个变量/函数/类型出处(声明或定义)的逻辑,所有有了域隔离,名字冲突就解决了。局部域和全局域除了会影响编译查找逻辑,还会影响变量的⽣命周期,命名空间域和类域不影响变量⽣命周期。
2026-08-03 19:02:09
390
21
原创 函数栈帧的创建与销毁:从汇编底层彻底搞懂函数调用
函数参数和函数返回值临时变量(包括函数的非静态的局部变量以及编译器自动生成的其他临时变量)保存上下文信息(包括在函数调用前后需要保持不变的寄存器)一句话理解:每调用一个函数,就会在栈上为它"分配一间房",这间房就叫栈帧。函数返回时"退房",空间被回收。1. 栈(stack)是现代计算机程序里最为重要的概念之一,几乎每一个程序都使用了栈,没有栈就没有函数,没有局部变量,也就没有我们如今看到的所有的计算机语言。
2026-07-23 18:22:49
532
24
原创 顺序表从入门到精通
List.h//存放数据//存放数据节点//LinkList等价于LNode*//C语言中上述结构体中嵌套的typedef等价于这里的两个typedef//给struct ListNode起别名LNode//给struct ListNode*起别名LinkList//用LinkList时,强调它是「整条链表的头指针」,代表链表的入口//用LNode*时,强调它是「指向单个节点的指针」,比如遍历用的临时指针//初始化//等价于LinkList ListInit();
2026-07-22 19:36:58
445
22
原创 C语言刷题1
定行数:确定上半部分几行、下半部分几行,给行号 i 取值范围。列表格:把 i 从 0 开始的每一行,手动数出空格数、字符数,填进表格。找公差:看相邻两行的数量变化是加几还是减几,确定公差。写公式:用「首项 + 公差 * i」写出通项公式。验边界:代入首行、末行、中间行,验证是否符合预期。举个简单例子:5 行菱形(对角线 5 个字符)上半部分 3 行,i=0、1、2空格:2、1、0 → 公式 2 - i字符:1、3、5 → 公式 2 * i + 1下半部分 2 行,i=0、1。
2026-07-02 16:15:03
519
21
原创 移除元素(Remove Element)题目详解:三种解法与优化实践
快慢指针:一个指针遍历,一个指针记录有效位置覆盖而非删除:通过覆盖无效元素实现"删除"效果原地操作:避免额外空间开销空间换时间vs时间换空间的权衡双指针是处理数组问题的利器原地修改是面试中的常见要求删除排序数组中的重复项移动零合并两个有序数组a- 等类似问题建议读者在理解基础上,自己手写代码实现,并尝试不同的测试用例,加深对双指针法的理解。
2026-06-05 09:39:23
1026
21
原创 数据结构:算法效率与复杂度分析详解
第一步:找出基本操作找到执行次数最多的那条语句通常是循环最内层的操作第二步:建立执行次数函数F(n)用数学表达式表示执行次数考虑循环的嵌套和条件第三步:用大O表示法简化去掉所有加法常数只保留最高阶项去掉最高阶项的系数第四步:考虑最坏情况分析算法在最坏输入下的性能这是评价算法性能的标准。
2026-06-04 08:42:47
1959
22
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅