- 博客(32)
- 收藏
- 关注
原创 C++——二叉搜索树
二叉搜索树是一种特殊的二叉树,如果根节点的左右子树不为空,则满足以下性质:1. 若左子树不为空,则左子树上所有结点的值小于(小于等于)该节点的值。2. 若右子树不为空,则右子树上所有结点的值大于(大于等于)该节点的值。3. 它的左右子树也分别都为二叉搜索树。4. 针对第一和第二条性质中的小于等于和大于等于,关键在于该二叉搜索树是否支持相同值的存储:后续将会讲解map/set;multiset/multimap,这些底层本质都是运用搜索二叉树,其中:map/set不支持相同值的插入存储;
2026-07-24 10:40:58
213
原创 C++——多态
首先,多态存在于继承关系下。去调用基类和派生类中的同一函数时,会由于对象的不同,从而产生不同的行为。public:public:void print(Person* p)//必要条件是用基类的指针或者引用来调用虚函数//具体调用到的是哪个,就看指针具体指向了一个派生类还是基类int main()Person p1;Student s1;print(&p1);print(&s1);return 0;这段程序实现了一个基类Person,内部存在一个Buyticket函数;
2026-07-21 10:08:45
214
原创 C++——继承
继承(inheritance)机制是面向对象程序设计使代码可以复⽤的最重要的手段,它允许我们在保持原有 类特性的基础上进行扩展,增加方法(成员函数)和属性(成员变量),这样产⽣新的类,称派⽣类。继承 呈现了⾯向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的函数层次的复用,继承是类设计层次的复用。
2026-07-19 12:51:20
223
原创 C++——模板进阶
在上一节的priority_queue讲解完成后,完成了一些常用C++容器的基础使用和底层实现,这篇博客开始将继续向后学习C++的内容。
2026-07-17 13:16:55
236
原创 C++容器——priority_queue的使用/底层实现和仿函数
priority_queue,包含在queue的头文件中。这是它的类模板定义,同样是通过容器适配器来实现底层。但是可以注意到,相比于stack和queue,多了一个类模板参数——仿函数,这个会在之后讲完priority_queue的底层实现之后再详细讲解,现在首先讲解priority_queue全使用默认参数的情况下的数据排列情况,之后再讲解仿函数的使用方法,以及传递不同的仿函数会有什么不同。
2026-07-13 18:58:46
225
原创 C++容器——stack和queue的使用和基础实现
deque也叫双端队列,是一种能够同时具有vector尾插伪善,支持方括号下标的随机访问(这就代表了,deque可以支持算法库种的sort函数使用)、同时支持list头插头删时间复杂度低的优势。可以简单的理解为deque同时具备了vector和list的一些优点。vectorr理解起来较为简单,本质是数组的结构,在C语言初级阶段已经大量接触并使用。vecotr最主要的优点是:尾插尾删效率高,同时支持方括号下标的随机访问;同时因为vector的数组结构,其内存空间是连续的,cpu缓存命中率高。
2026-07-09 15:16:35
176
原创 C++容器——list的基础实现
C++容器中的list,本质是C语言基础数据结构中的链表结构。C++各类容器的使用方法差别不大,通过vector这个类模板的应用,其余类模板的使用也几乎是以相同的方法来实现。本篇博客将重点讲述list的基础底层实现。通过string和vector的底层实现,我们对类模板的使用场景有了进一步的印象;同时,我们对于迭代器有了基础的认知,通过对于迭代器的使用,我们发现迭代器是一个类似于指针一样的东西。
2026-07-06 15:39:36
257
原创 C++容器——vector的基本实现(下)
在上一篇博客中已经讲述了vector的基本使用方法。为了更好的理解其底层原理和提高一定的代码能力,本篇博客将针对vector进行一个简单的基础实现。
2026-07-02 18:50:18
198
原创 C++容器——vector的使用(上)
vector是基础数据结构中的顺序表结构。其实现方式为模板类型,这就让其应用范围更加广泛。可以在其内部存放任意内置类型,甚至可以存放自定义类型如string、vector、和自定义类型等。
2026-07-01 09:30:23
320
原创 C++容器——string的基础实现(下)
上篇博客主要讲了std标准库中string容器的基本使用方法。为了更加透彻的理解string,同时也是增强基础代码能力,所以来对string进行一个基本的实现。
2026-06-29 09:27:58
286
原创 C++——内存管理和初阶模板
但是通过汇编可以看出,其开始处理时,实际放置了44个字节,初始的4个字节存放的数据是10,之后返回从第二个地址开始的值,即正常的10个整形 40个字节。ptr4指向了一块10个整形数据的空间,并将其从前到后分别初始化为1,2,3,4,5,0......;先看主程序,直接调用Add函数模板,然后进行参数传递,这样实现函数模板实例化的方式叫做隐式实例化,即编译器自动根据所传递参数的类型,推演出函数模板参数的类型,进而生成相应的函数。这样的缺点是,无法实现两个类型不同参数的传递,否则会报错。
2026-03-07 16:40:54
322
原创 类与对象(下)
如这段代码,定义了类A和类B,在A中声明B是A的友元类,所以B的函数均默认为A的友元函数,即在B内定义的函数fun1可以访问到A中的_ a1 和 _a2,在main函数中实例化对象a 和b,利用b调用函数fun1,并传参给对象a,可以在打印界面看到输出了_a1 和 _a2的值。在Date的类中,成员变量有一个类型A的类变量,但A没有默认构造函数,所以对类型A的变量a,必须要在初始化列表中初始化,不能在构造函数函数体内进行赋值。之前的章节中,学习到了类的基本定义方式,访问限定符,类实例化的方式;
2026-03-04 00:32:09
369
原创 类与对象(中)——日期类的综合实现
日期加等一个天数,其返回值类型仍为日期类,并且该类对象仍然存在,所以可以返回日期类的引用,参数为需要增加的天数。在实现+的重载时,由于不需要原对象内存中的数据发生变化,所以利用拷贝构造函数生成了一份拷贝tmp,然后对tmp进行+=的调用即可。只需要找到两个日期类中较大的类,然后另较小的类不断自增++,直到两个日期相同,++的循环次数,就是两个日期之间相差的天数。首先对于流提取,直接利用cin的引用类型进行年月日的输入即可,但要利用Cheak函数进行判断,如果不对的话,进行提示,持续输入,直到输入正确为止。
2026-02-26 19:35:44
460
原创 类与对象(中)——运算符重载
需要注意的是,在语法上,运算符可以实现重载,但在实际意义上,有些运算符是不需要进行重载,比如日期+日期的运算符就不需要进行重载,其没有实际意义。如果将运算符重载函数定义在类外,那么就无法访问到私有的成员变量,这里提供四种解决方法的思路:1.提供一个get函数,用来获取类内成员变量的数据。4.将重载放到类中。在对成员函数传参时,会默认存在一个Date* const this的成员函数(以日期类为例),这个成员函数的const修饰this指针,标识this指针不可以改变,而*this的对象可以被改变。
2026-02-25 20:39:57
1095
原创 类与对象(中)——构造函数、析构函数和拷贝构造函数
例如在数据结构栈的练习题中,写过一个题目叫做用两个栈实现一个队列的功能,其具体思路是创建两个栈,放到队列的类中,那么这个队列类就是由两个栈类实现的类,其在调用构造函数时会自动调用栈的构造函数。如上面的栈,首先实现了一个构造函数,在其内部实现了一个构造函数,创建了一个大小为4的数组,然后对top和capacity进行相应的定义。对于上面的日期类,不需要写析构函数,因为没有进行动态内存的开辟,所以利用编译器自动生成的析构函数即可,通过程序调试可以看出,自动生成的析构函数没有对成员变量做任何处理。
2026-02-24 14:57:59
997
原创 C++类与对象(上)
本质是为了节省空间,如果创建了100个利用该类实例化的对象,那么调用该函数的过程中就需要多存储100个完全一致的call指令(函数的地址为第一条指令的地址),函数地址完全相同,所以就不需要在类内对其进行存储。根据C语言中结构体的内存对齐规则,A和B的类内,没有任何成员变量,其理论大小应该是0,但是实际输出A和B的大小,发现为1。这个1,是类A B的占位标识符,为了证明该类存在。在本章节的博客中,引入在C++中知名的类与对象的概念,同时将其和C语言中的结构体做对比,介绍类域对象的基本定义、
2026-02-21 18:44:07
1004
原创 C++初始03——常引用、内联函数和nullptr
这个情况就类似于下面的指针示例,对a的地址指定一个const int* 类型的指针p1,*p1无法被修改,即a无法被修改,所以如果此时定义了一个指针变量int* p2 = p1,这样写语法错误,因为*p1无法修改,而*p2却可以修改,所以正确写法应该是const int* p2 = p1,这样*p2和*p1均不可被修改,语法才能正常通过。再看下一个示例,定义了一个整型变量b,如果定义一个const修饰的引用,在语法上可以通过,这相当于是权限缩小,原始变量b可以修改,而其引用rb无法修改,这样是可行的。
2026-02-19 21:59:31
994
原创 C++初始02——函数参数缺省、函数重载和引用
例如该示例,定义函数 f1,返回一个ret1的引用,而 ret1 为 f1 函数中定义出的临时变量,在 f1调用结束之后,f1的函数栈帧销毁,而返回的引用对象仍然为该块空间的值,所以会形成野引用,导致程序运行不稳定。例如同时想实现一个交换函数Swap,如果交换不同类型的值,例如double和int,则需要写两个Swap函数,而在C语言中不可以同时命名为Swap,需要对函数名称进行一定程度的区分,例如Swap_int 、Swap_double。如果进行传参,则会返回传参的两个值相加的结果。
2026-02-17 16:58:05
626
原创 C++初识—— 命名空间和基本输入输出
在主函数中,如果特定输出example域中的rand变量的值,则需要利用双冒号,example::rand,表示定向输出example域中的rand变量的值。如这段代码实例,在example的命名空间中,定义了example1和example2的两个命名空间,如果想要输出example1中a的值,则需要example::example1::a。在C++中,输入和输出定义到 iostream 的头文件中,其是Input Out Stream的缩写,是标准的输入输出流库,输入输出对象。
2026-02-17 15:50:42
653
原创 插入排序04——非递归实现归并排序以及对文件数据的归并排序
fscanf函数如果读取到文件末尾,则会返回EOF,所以如果返回了EOF,代表n个数据没有全部读取完成,此时表示数组下标 的 i,就是当前数组存放的数组个数。从源数据中读取n个数据,先存放到一个数组中。之后将mfile重命名为file1,再次从数据文件中读取n个数据放入到file2中,和file1归并,放入到mfile中。在之前实现归并排序的过程中,先根据左右下标,找到中间节点,然后利用中间节点不断的递归直到最后只剩下一个节点,然后利用两个有序数组的合并进行排序,直到最后完成对整个数组的排序。
2026-02-14 13:23:29
582
原创 排序算法03——快速排序之三路查找和自省排序
此时cur位置的数据大于key,所以和right进行交换,right自减,指向倒数第二个位置。交换后,cur的位置为9,仍然大于key,所以继续和right进行交换,交换完后自减,right指向倒数第三个位置。交换完后,此时cur位置的数据为4,小于key,所以和left进行交换,交换完后,cur自增,left自增。如上图所示,默认最左侧的值为key,在在对key寻找合适位置的过程中,有着多个相同的数据,将这些相同的数据放到一起,left和right下标最终是用来指示这些相同的数据的左右位置。
2026-02-13 14:42:43
925
原创 排序算法02——交换排序和计数排序
初始时,prev和key同时在最左侧,而cur指针在left+1的位置,cur向前移动寻找小于key的元素,然后prev先向前走一步再和cur交换,这样就实现了将小元素集中到数组前侧,大元素集中到数组后侧。lomuto法代码实现较为简单,整体思路为:创建两个指针,prev和cur,cur指针在prev的前侧, cur寻找值小于key的值,然后prev先前进一步,在和cur进行交换。根据key值可求出左子树的范围[left,key-1]和右子树的范围[key+1,right],进行类似二叉树的递归方式。
2026-02-12 18:56:01
720
原创 排序算法01——插入排序和选择排序
需要额外注意的是,如果maxi指向的正好是begin所在的元素,那么需要将maxi赋值为mini,因为先交换了begin和mini的元素,此时mini所指向位置的数据是交换之前begin所指向位置的数据,所以交换后mini位置的数据是最大值。当前数组为[1,3,4,5,2],整理数组使其有序,本质就是将2放到数组的合适位置,利用两个下标,p和p+1,其中p下标指向已经有序数组的最后一个元素的位置,p+1自然就指向了下一个待排序元素的位置。之后将数组范围缩小,再次进行查找,直到数组左右下标指向同一个元素。
2026-02-11 21:24:33
566
原创 数据结构07——二叉树3(链式二叉树)
D不为空,打印D的值,进入D的左子树,D的左子树为N,直接打印NULL后返回,进入D的右子树,右子树也为NULL,打印NULL返回,D的函数全过程执行完成,返回B;继续执行B函数中的下一条指令,进入B的右子树,为NULL,打印NULL直接返回,B函数整个函数执行完成,返回A,执行A的下一条置零,进入A的右子树。参数为E,不为空,打印出E,进入E的左子树,为空,打印NULL直接返回执行下一条,进入E的右子树,为空,打印出NULL,直接返回,E整个执行完成,返回到C中,执行C的下一条指令,进入C的右子树;
2026-02-07 22:37:50
615
原创 数据结构06——二叉树2(堆)
每次新数据如果比堆顶最小值还要大,将其放入堆中,调整完后,又会将一个最小的元素放到堆顶的位置,从而与下一个元素进行替换操作,每次替换一个堆中的最小值,那么所有数据遍历完后,堆中剩下的就是所有数据中最大的k个数据。两个元素进行比较,发现子节点仍然大于父节点,进行数据交换。之后进行Top_K问题的求解:读取文件,将文件中的一个数据存放入变量tmp中,将变量tmp与堆顶元素进行比较,如果比堆顶元素大,将其替换为新的堆顶数据,之后对于新的堆进行向下调整处理,直到循环1千万次,遍历完整个txt文件中的数据。
2026-02-06 10:11:19
934
原创 数据结构05——二叉树1
二叉链表示,存储节点的数据以及左子节点和右子节点的指针,三叉链则是在节点数据以及左右子节点的指针基础之上,增加了指向父节点的指针。就是每个节点都有左右两个子节点构成。图1和图2的错误类型相同,均为子树之间有交叉,图三的错误为根节点与子节点的子节点相联系。如果一个节点有子节点,那么这个节点称为子节点的父节点。在树的结构中,子节点有且仅有一个父节点(前驱节点),有>=0个子节点。:在一颗树上,从最初的根节点到该节点的路径中的所有点都可以称为该子节点的祖先。有一个特殊的节点称为根节点,其没有前驱节点(父节点)
2026-02-05 23:17:06
788
原创 数据结构04——栈和队列
对于队列的实现,通过思路来看,仍然可以用数组和链表进行实现:对于数组来说,将数组尾部当作队尾进行数据的插入,其时间复杂度位O(1),将数组头部当作队头进行数据删除则需要将数组中其余元素依次向前挪动,时间复杂度位O(N);之后需要考虑头节点是否为空的情况:如果头节点为空,就代表所创建的新节点为头节点,改变队列的头指针和尾指针都指向新节点。队列的销毁与栈销毁不同的是,队列的底层实现利用的是链表,而链表的每个节点又是单独申请的一块结构体空间,所以要对每个节点进行手动释放,最后再将头和尾指针置为空。
2026-01-31 20:53:06
603
原创 数据结构03——单链表
考虑一般情况下,需要遍历原始链表,找到pos节点的上一个节点ptr,然后另ptr节点指向pos的下一个节点,就实现了将pos节点跳过,既删除的操作,最后释放pos节点。通常情况下,在给定pos位置之前插入数据,先遍历元素找到pos的前一个节点,然后让该节点的next指向创建出的新节点NewNode,NewNode节点的next指向pos节点即可。删除pos之后的节点,仍然只需要给出要删除的pos即可,让pos跳过pos的下一个节点,指向pos的下一个的下一个节点,既pos->next->next。
2026-01-27 12:04:40
585
原创 数据结构02——顺序表
尾删数据,不需要真正把最后一个元素删除,只需要遍历数组的时候让其索引不到即可,所以将size向前挪动一位,这样下次不论是头插还是尾插数据,都会将这个元素替换为新元素。指定位置之前插入数据,首先仍需要判断空间是否足够,然后将这个位置的数据依次向后挪动,将这个位置留出一个空间,再将数据x放入。顺序表使用数组来实现的,其与数组最大的不同在于,对数组进行了一定程度的封装,通过函数实现了较为便捷的增删查改的操作。从该位置开始,将之后的数据提前,将pos位置的数据覆盖即可达到指定位置删除的效果。
2026-01-26 16:55:38
586
原创 数据结构01——时间复杂度和空间复杂度
首先看这个代码的for循环中出现了变量N,while循环中虽然也出现了变量M,但其为定值,循环10次,大致可以写为O(N+10),而根据第一条规则,只保留高阶项,最后答案是O(N)。再次回到开头的题目实例,如果用依次向后移动的方法,其时间复杂度为O(N^2),而题目中提供的元素个数最多为10^5,总时间为10^10ms相当于10^7s,会超过时间限制。而对于fun5的递归来说,空间复杂度 = 单次运行的空间复杂度* 递归次数,单次递归的空间复杂度为O(1),共有n次,所以总的空间复杂度为O(N);
2026-01-25 18:36:28
714
原创 C语言循环判断结构
分支和循环语句是C语言编程的基础,掌握它们对于编写高效、可读性强的代码至关重要。通过练习不同场景的应用,如:使用for循环处理确定次数的任务使用while循环处理不确定次数的任务合理使用break和continue优化循环结合if语句实现复杂条件判断。
2025-12-07 15:33:10
591
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅