- 博客(50)
- 收藏
- 关注
原创 【数据结构】二叉搜索树的递归与非递归实现
本文系统介绍了二叉搜索树(BST)的数据结构及其实现。二叉搜索树是一种高效的查找结构,具有左子树值小于根节点、右子树值大于根节点的特性。文章详细阐述了BST的构造与销毁、插入、查找和删除等核心操作,包括递归与非递归两种实现方式。特别对复杂的删除操作进行了重点分析,提出伪删除法处理左右子树均非空的情况。此外,还介绍了BST的两种应用模型:K模型(纯键值查找)和KV模型(键值对查找),并提供了完整的C++实现代码。最后,文章给出验证BST有效性的算法,确保树结构符合定义要求。
2025-10-05 16:17:36
683
2
原创 【数据结构】BF与KMP的实现
本文介绍了两种经典的字符串匹配算法:暴力(BF)算法和KMP算法。BF算法通过逐个比较字符实现简单匹配,但效率较低。KMP算法通过预处理模式串生成next数组,利用最长公共真前后缀信息避免回溯,提高了匹配效率。文章详细讲解了两种算法的原理、实现步骤,并通过图示说明匹配过程。针对KMP算法,重点分析了next数组的构建方法,并提出了优化方案nextval数组以处理特殊匹配情况。最后给出了两种算法的C语言实现代码,包括基本版本和优化版本,展现了从理论到实践的完整过程。
2025-10-02 21:36:28
676
2
原创 【数据结构】堆、计数、桶、基数排序的实现
本文介绍了四种经典排序算法:堆排序、计数排序、桶排序和魁基数排序。堆排序通过建立最大/最小堆并重复调整堆 Thực hiện排序;计数排序利用统计元素出现次数实现非比较排序;桶排序将元素分配到多个桶中分别排序后合并;基数排序则按位数从低到高依次排序。每种算法都详细说明了思想、步骤和代码实现,并配有动画演示。这些算法各具特色,适用于不同场景,其中堆排序时间复杂度为O(nlogn),计数/桶/基数排序在特定条件下可达线性时间复杂度。
2025-10-01 10:39:38
4893
2
原创 【数据结构】快速排序与归并排序的实现
本文介绍了快速排序和归并排序两种算法。快速排序采用分治思想,通过基准值将数组分为左右子序列,详细讲解了Hoare法、挖坑法和双指针法三种实现方式,并给出优化策略如三数取中和小区间优化。归并排序同样基于分治法,通过递归将数组分解为有序子序列再合并,提供了代码实现和优化方法,包括小区间优化和有序区间判断。两种算法的时间复杂度均为O(nlogn),但通过优化可进一步提升性能。
2025-09-30 19:23:07
810
原创 【数据结构】冒泡、选择、插入、希尔排序的实现
本文介绍了四种基础排序算法:冒泡排序通过相邻元素比较交换将最大元素移到末尾;选择排序每次遍历选择最小/最大元素交换到起始/末尾位置;插入排序构建有序序列并逐个插入未排序元素;希尔排序是插入排序的优化,通过gap分组预排序提升效率。每种算法均包含思想描述、具体步骤和C语言实现代码,其中冒泡排序和选择排序还提供了优化版本。这些算法虽然时间复杂度较高(多为O(n²)),但作为基础排序方法,对理解更复杂算法具有重要意义。
2025-09-24 18:13:58
1415
5
原创 【数据结构】堆排序
堆排序是一种基于堆数据结构的排序算法,分为构建堆和排序两个阶段。升序建大堆,降序建小堆。构建堆可采用向上/向下调整算法,核心是通过交换父子节点维护堆性质。排序阶段将堆顶元素与末尾元素交换,缩小堆范围并调整堆,重复操作直至完成排序。时间复杂度为O(NlogN),空间复杂度O(1)。代码实现包含交换函数、调整函数和主排序函数,通过大堆实现升序或小堆实现降序。测试案例验证了算法的正确性。
2025-09-24 17:17:23
459
1
原创 【数据结构】利用堆解决 TopK 问题
本文介绍了TopK问题的解决方案,通过堆数据结构高效地找出前K个最大/最小元素。关键点在于:求前K个最大数时使用小堆,前K个最小数时使用大堆。具体实现步骤包括:1)用前K个数建堆;2)剩余元素与堆顶比较,替换后调整堆;3)最终堆中的K个数即为结果。文中提供了完整的C语言实现代码,包括堆的初始化、插入、删除等操作,并通过随机生成百万级数据验证了算法的有效性。该方法相比直接排序更高效,特别适合处理大数据量的TopK问题。
2025-09-20 13:58:57
468
1
原创 【数据结构】堆的概念
本文系统地介绍了堆数据结构的概念、性质及实现方法。堆是一种特殊的完全二叉树,分为大根堆(父节点值≥子节点)和小根堆(父节点值≤子节点),主要用于堆排序和TopK问题。文章详细讲解了用数组实现堆的具体方法,包括初始化、销毁、插入、删除等核心操作,重点阐述了向上调整(AdjustUp)和向下调整(AdjustDown)算法:插入时新元素置于末尾并通过向上调整维持堆性质,删除时将堆顶与末尾交换后向下调整。文中提供了完整的C语言实现代码,包含堆的结构定义、接口函数及具体实现,展现了堆操作的关键流程和算法思想。
2025-09-19 16:16:25
735
1
原创 【数据结构】二叉树的概念
本文系统介绍了二叉树的基本概念和重要特性。主要内容包括:1.二叉树定义:每个节点最多有两个子节点,且子树有左右之分的有序树;2.特殊二叉树类型:满二叉树(每层节点数达最大值)和完全二叉树(前h-1层满,最后一层左连续);3.二叉树性质:包括节点数计算、叶子节点与度为2节点的关系等;4.存储方式:数组存储适用于完全二叉树,链式存储更通用;5.遍历方法:详细说明了前序、中序、后序和层序遍历的实现方式。这些知识是理解和应用二叉树数据结构的基础。
2025-09-14 15:36:51
1201
1
原创 【数据结构】树的概念
树是一种非线性层次结构的数据结构,由根节点和多棵互不相交的子树组成,具有递归定义特性。树结构包含根节点、叶子节点、分支节点等概念,以及度、层次、高度等属性。树可通过双亲表示法、孩子表示法和左右孩子兄弟表示法三种方式存储。树结构广泛应用于文件目录、网络拓扑、最短路径计算、搜索引擎等领域,是计算机科学中重要的基础数据结构。其分层特性使其能有效表示现实中的层次关系。
2025-09-14 14:28:25
669
原创 【数据结构】队列详解
摘要:本文详细介绍了队列(Queue)的数据结构实现。队列是一种遵循FIFO(先进先出)原则的线性表,支持在队尾插入元素和在队头删除元素。文章给出了链式队列的结构定义,包括节点结构(QueueNode)和队列结构(Queue)。重点阐述了队列的各接口函数实现,包括初始化(QueueInit)、销毁(QueueDestroy)、判断空(QueueEmpty)、入队(QueuePush)、出队(QueuePop)、获取队头/队尾元素(QueueFront/QueueBack)、获取元素个数(QueueSize)
2025-09-11 18:03:34
1360
2
原创 【数据结构】栈详解
本文介绍了栈的基本概念、实现方式及具体操作。栈是一种遵循LIFO原则的线性结构,支持压栈和出栈操作。实现方式主要有数组栈(推荐)和链式栈两种,前者具有更高的缓存利用率和操作效率。文章详细讲解了动态栈的实现,包括初始化、销毁、判空、入栈、出栈、获取栈顶元素和计算栈大小等核心功能,并提供了完整的C语言代码示例。重点分析了数组栈的扩容机制和top指针的两种不同定义方式对操作的影响。
2025-09-09 18:20:28
741
2
原创 【数据结构】带哨兵位双向循环链表
本文详细介绍了带头双向循环链表的实现。主要包含三个部分:1)链表分类,重点讲解了无头单向非循环链表和带头双向循环链表的特点及用途;2)双向循环链表的定义,包括结点结构定义和接口函数声明;3)接口函数的具体实现,包括初始化、插入/删除、查找等操作,特别强调了DListInsert和DListErase这两个核心接口的实现及其复用价值。通过代码示例展示了如何利用双向链表的结构优势简化操作,如头插/头删、尾插/尾删等。完整代码实现了带头双向循环链表的所有基本功能。
2025-09-06 17:50:40
1321
1
原创 【数据结构】单链表详解
本文系统介绍了链表数据结构及其实现方法。主要内容包括:链表与顺序表的对比分析,单链表的结构定义和基本操作接口(创建、打印、插入、删除、查找等)的实现细节,并通过完整代码展示了一个单链表的完整实现方案。文章重点讲解了链表的两种存储结构(逻辑结构和物理结构),详细分析了顺序表和链表各自的优缺点,并提供了多种操作方法的实现思路(如尾插的两种实现方式)。文中还通过示例代码和运行结果展示了每个接口函数的具体应用场景。
2025-08-26 22:34:53
963
3
原创 【数据结构】顺序表详解
本文详细介绍了线性表的顺序存储结构——顺序表。主要内容包括顺序表的基本概念、静态与动态实现方式、核心接口函数(初始化、增删查改等)的具体实现。顺序表通过数组实现,要求数据连续存储,支持高效的随机访问。文章重点讲解了动态顺序表的扩容机制、头尾插入删除操作、指定位置操作等关键功能的实现逻辑,并提供了完整的C语言代码实现。通过多个测试用例验证了顺序表各种操作的可行性,最后总结了顺序表的优缺点及适用场景。
2025-08-25 16:49:25
1036
1
原创 【数据结构】时间复杂度 | 空间复杂度
【摘要】本文系统介绍了数据结构和算法的基本概念及其重要性。数据结构研究数据的组织方式和相互关系,算法则是解决问题的步骤描述。衡量算法效率主要考察时间复杂度和空间复杂度,其中时间复杂度(大O表示法)更为关键,反映算法执行时间随数据规模增长的变化趋势。文章详细讲解了复杂度分析方法,包括常见类型如O(1)、O(N)、O(N²)等,并通过多个实例(如冒泡排序、二分查找、递归算法等)展示了具体计算方法。空间复杂度主要关注算法运行时的额外空间消耗。随着硬件发展,现代算法分析更侧重时间复杂度优化。
2025-08-24 18:15:09
1052
原创 (5)软件包管理器 yum | Vim 编辑器 | Vim 文本批量化操作 | 配置 Vim
本文介绍了Linux中yum软件包管理器和Vim编辑器的使用。主要内容包括:1. yum安装软件的三种方式(源码、rpm、yum)及其优缺点,重点讲解yum安装的便捷性;2. Vim编辑器的多模式操作(默认模式、插入模式、底行模式)及模式切换方法;3. Vim的文本批量化操作,包括复制(yy)、粘贴(p)、剪贴(dd)、撤销(u)等常用指令;4. 光标快速定位技巧(gg/G)和字符修改替换操作;5. 最后提供了Vim的一键配置方法。文章通过实例演示了Linux环境下软件安装和文本编辑的高效操作方式。
2025-08-20 11:19:56
1236
1
原创 (4)shell 命令及运行原理 | Linux 权限 | 文件权限的修改和转让 | 目录的权限 | Sticky bit 粘滞位
本文主要介绍了Linux系统中shell命令的运行原理及权限管理机制。首先解释了shell作为命令行解释器的作用,即作为用户与内核(kernel)交互的桥梁。其次详细阐述了Linux的权限系统,包括用户分类(root和普通用户)、文件权限表示方法(字符和八进制数值)、以及权限修改命令(chmod/chown/chgrp)。文章还分析了目录权限的特殊性,解释了umask权限掩码的作用机制,并介绍了粘滞位(Sticky bit)在共享目录中的应用,可防止其他用户删除不属于自己的文件。
2025-08-18 18:44:24
869
2
原创 (3)重定向 | 时间相关指令 | 文件查找 | 打包与压缩
uname 可显示 Linux 主机所用的操作系统的版本、硬件的名称等基本信息。
2025-07-22 18:27:20
685
2
原创 (2)man 手册 | 复制文件或目录 | 移动文件和重命名 | 查看目标文件内容
在写 C / C++ 的时候,我们如果记不得某个函数的用法,可以去查手册。Linux 的命令有很多参数,我们不可能全部记住,但我们可以通过查看联机手册来获取帮助。比如,我们想搜一下 printf ,这时我们可以去问 ---- man在 Linux 中,printf 也是一个命令。man 不仅可以用来查命令,还可以用来查 C 语言函数。因为 Linux 这个操作系统本身就是由 C 语言写的,所有它的 man 手册默认是带 C 语言的标准手册的。
2025-07-19 16:36:24
1119
原创 (1)目录内容的显示 | 目录跳转 | 基本创建与删除操作
ls 选项 目录或文件ls:显示当前目录下的所有文件① 对于目录来说,该命令列出目录下的 所有子目录和文件② 对于文件来说,列出文件名及其他信息我们先用 touch 先创建一个文件之后再输出 ls:当然,我们也可以用 ls 直接查看到一些目录文件。我们在输入指令的时候一定要把空格带好显示当前目录下,我们当前目录是谁呢?如何知道?$ pwd。
2025-07-14 14:08:57
975
原创 二十四、映射类
STL 的 map 是关联容器,按照特定顺序存储关联,由键和值组成键值对,key 通常用于排序和唯一地标识元素,value 中存储与 key 关联的内容。key 和 value 的类型可以不同,在 map 内部,key 和 value 通过成员类型 value_type 绑定。value_type 实际上就是 pair 类型底层基于红黑树,是一种自平衡的二叉搜索树,能确保在插入和删除元素时维持良好的性能。map 通常被实现为二叉搜索树,更准确的说是平衡二叉搜索树。
2025-02-07 20:18:00
1050
原创 二十三、集合类
通过插入新的元素来扩展容器,通过插入的元素数量来增加容器的大小。因为集合中的元素是唯一的,插入操作会检查每个插入的元素是否等同于已经存在于容器中的元素。如果是,则不插入该元素,返回到这个现有元素的迭代器。在内部,集合容器保持着其所有元素按照比较对象的标准进行排序,这些元素总是按照这个排序插入到它各自的位置, Set 是 排序 + 去重。官方文章介绍:https://cplusplus.com/reference/set/set/Set 底层是平衡二叉搜索树,是基于红黑树实现的。
2025-02-02 22:36:26
819
原创 二十二、BS树
这里我们用模板,模板参数我们给了一个 K,表示 key 的意思K _key;:_key(key){}下面我们来定义整个树,BSTreeNode 也有些长了,我们不如将其 typedef 成 Node。
2024-11-05 14:42:59
1080
2
原创 二十、多态
在虚函数的后面写上 =0,我们称这个虚函数为纯虚函数。包含纯虚函数的类,就是抽象类(也叫接口类)。/* 抽象类 */class Carpublic:// 纯虚函数抽象类不能实例化出对象,子类即使继承后也不能实例化对象。/* 抽象类 */class Carpublic:// 如果父类是抽象类,子类必须重写才能实例化public:{ // 重写cout << "BMW-操控性" << endl;b.Drive();return 0;
2024-10-08 16:28:37
932
原创 十九、继承
派生类 继承方式 基类👇 👇 👇public:// 学号Student 是子类,我们也称之为派生类。Person 是父类,我们也称之为基类。我们可以把 Person 和 Student 看作是父子关系,继承资产,这里的继承方式是 public,即公有继承,还有其他的继承方式。
2024-09-25 14:43:22
774
原创 十七、模拟 实现栈和队列类
从上层角度看,其默认是一个双端队列,底层用什么去实现并不重要,只要符合要求即可,保存栈的性质,复用容器的代码我们可以用 const 来限定成员函数,这意味着不能在类对象上调用这些函数来修改内部状态,避免了潜在的危险。
2024-08-27 18:22:14
969
原创 十六、栈和队列
① 队列是一种容器适配器,专门用在先进先出上下文中操作,其中从一端插入元素,从另一端提取元素② 队列作为容器适配器实现,容器适配器即将特定容器类封装作为其底层容器类,queue 提供一组特定的成员函数来访问其元素,元素从队尾入队列,从 队头出队列③ 标准容器 deque、list 符合这些需求,默认情况下,如果没有为 queue 指定特定的底层容器,默认情况下使用 deque④ queue 的底层容器可以是任何标准的容器模板或者一些其他特定的容器类,这些容器应该支持以下操作:empty:判空操作。
2024-08-26 19:10:38
1076
原创 十五、迭代器适配器
上一章 list 迭代器实现时,我们提到了反向迭代器的实现代码:我们先讨论一个问题,什么是迭代器适配器?想了解这里的适配器,我们不如先看看电源适配器:电源适配器是进行转换的,本质上可以理解为是一个变压器标准家庭电压为 220V,我们设备用电其实并不需要那么高而电源适配器可以使较高的交流电压降到合适于手机电池的直流工作电压也就是说,电源适配器使用来转换的反向迭代器和正向迭代器非常像,区别是:反向迭代器和正向迭代器加加的方向不一样(即正向迭代器加加是向后走,反向迭代器加加是向前走)基于这一系列的原因,在实
2024-08-21 20:04:05
679
原创 十四、模拟实现 list 类
迭代器是借助结点的指针访问修改链表的,结点属于链表,不属于迭代器,所以不用管它的释放问题,因此,拷贝构造、赋值重载和析构,这些都不需要自己实现,默认生成的即可。
2024-08-18 23:20:36
1189
原创 十三、list 类
我们已经学习过 string 和 vector 了,想必大家已经掌握了查文档的能力现在我们去学习如何使用 list ,最好仍然打开文档去学习允许在任意位置进行 O(1) 插入和删除的顺序容器,并提供双向迭代器双向链表中每个元素存储在互不相关的独立结点中,在结点中通过两个指针指向其前后元素最大的不同就是 forward_list 是单链表,只能向前迭代list 通常在任意位置进行插入、删除元素的效率更高,因为是 O(1)
2024-08-13 11:56:10
927
原创 十二、模拟实现 vector
我们发现,成员函数和之前模拟实现的 string 的写法不一样了,但虽然表面上看起来不一样,但实际表达的效果是大同小异的:我们用指针记录 _start,_finish,_end_of_storage 的位置,只需要指针减指针就可以得到大小和容量再说回代码的实现,为了和库中的 vector 进行区分,我们这里依然用命名空间包含起来。我们这里造一个 vector 的类模板去适应各种类型,我们用 typedef 将 T* 重命名为 iterator。
2024-08-12 19:38:43
680
2
原创 十一、vector 类
① vector 是表示可变大小数组的序列容器,既像数组,又不像数组同样采用连续存储空间存储元素,可以使用下标访问元素大小是可以动态改变的② 本质上来说,vector 使用动态分配数组来存储它的元素当新元素插入时,为了增加存储空间,这个数组就需要被大小。具体做法是分配一个新的数组,然后将全部元素转移到这个新的数组。就时间而言,这是一个相对代价较高的任务,因为每当一个新的元素加入后,vector 并不会每次都重新分配大小。
2024-08-09 16:30:12
1051
3
原创 十、模拟实现 String
现代写法在 string 中体现的优势还不够大,因为好像和传统写法差不多。但是到后面我们实现 vector、list 的时候,你会发现现代写法的优势真的是太大了。现代写法写起来会更简单些,比如如果是个链表,传统写法就不是 strcpy 这么简单的了,你还要一个一个结点拷贝过去,但是现代写法只需要调用 swap 交换一下就可以了。现代写法更加简洁,只是在 string 这里优势体现的不明显罢了,我们后面可以慢慢体会。
2024-08-08 20:55:07
862
原创 九、String 类
① string 是表示字符串的字符串类。② 该类的接口与常规容器的接口基本相同,又添加了一些专门用来操作字符串的常规操作。
2024-08-06 22:44:44
1203
原创 八、STL介绍
它不仅是一个可重复的组件库,还是一个包含数据结构与算法框架,是封装好的数据结构举个例子:比如你有一个冰箱,冰箱突然坏了,但你不知道它制冷的原理,制冷的原理就是数据结构,冰箱提供的功能就是STL看看百度上的有关内容:标准模板库(Standard Template Library,STL)是开发的一系列软件的统称。它是由Alexander Stepanov、Meng Lee和David R Musser在工作时所开发出来的。虽说它主要出现到C++中,但在被引入C++之前该技术就已经存在了很长时间。
2024-08-03 22:37:37
916
原创 七、内存管理
① 调用 operator new 申请空间② 在申请空间上调用构造函数,完成构造① 在空间上调用析构函数,完成对象中资源的清理工作② 调用 operator delete 释放空间① 调用 operator new[] ,在 operator new[] 中实际调用 operator new 完成 N 个对象空间的申请② 在申请空间上调用 N 次构造函数,完成初始化① 在释放的对象空间上执行 N 次析构函数,完成 N 个对象中资源的清理工作。
2024-08-01 23:45:04
802
原创 五、函数模板与类模板
利用模板机制可以显著减少冗余信息,能大幅度地节约程序代码,进一步提高面向对象程序的可重用性和可维护性。模板是实现代码重用机制的一种工具,它可以实现类型参数化,即把类型定义为参数,从而实现代码的重用,使得一段程序可以用于处理多种不同类型的对象,大幅度地提高程序设计的效率。
2024-07-18 11:08:51
1098
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅