
C++从入门到掌握
文章平均质量分 87
对于C++的学习之路的分享
Dream_Snowar
这个作者很懒,什么都没留下…
展开
-
[C++][STL]unordered_set类和unordered_map类
在C++98中,STL提供了底层为红黑树结构的一系列关联式容器,在查询时效率可达到logN,即最差情况下需要比较红黑树的高度次,当树中的节点非常多时,查询效率也不理想。最好的查询是,进行很少的比较次数就能够将元素找到。在C++11中,STL又提供了4个unordered系列的关联式容器,这四个容器与红黑树结构的关联式容器使用方式基本类似,只是其底层结构不同。unordered_xxx系列与map和set容器的用法上几乎没有任何区别他们的区别就是。原创 2025-03-27 22:16:55 · 853 阅读 · 0 评论 -
[C++进阶]第三十五节 AVL树
如下所示,我们将AVL结点的值定义为一个pair对象,目的是使用key-value模型。bf是一个平衡因子。这里我们还需要使用三叉链结构int _bf;原创 2024-09-17 17:17:36 · 959 阅读 · 0 评论 -
[C++进阶&数据结构]第三十四节 map和set的相关题目
代码解析:6.单词识别代码解析:本篇类似番外,目的只是方便大家巩固,如有错误感谢指正原创 2024-08-30 23:54:50 · 1112 阅读 · 0 评论 -
[C++番外] 第三十三节 抛异常
异常总体而言,利大于弊,所以工程中我们还是鼓励使用异常的。原创 2024-08-27 22:54:01 · 1287 阅读 · 0 评论 -
[C++进阶]第三十二节 map和set
如下图所示:我们可以注意到它的模板参数是要比其他容器多一个的,这个容器我们也可以看到是一个仿函数。我们使用优先级队列的时候也用过这个仿函数。集合是按照特定顺序存储唯一元素的容器。在一个集合中,元素的值也标识它(值本身就是键,类型为 T),并且每个值必须是唯一的。集合中元素的值在容器中不能修改(元素总是 const 类型的),但是可以从容器中插入或删除元素。在内部,集合中的元素总是按照其内部比较对象(类型为 Compare )指示的特定严格弱排序标准排序。原创 2024-08-21 00:03:30 · 1226 阅读 · 0 评论 -
[C++进阶]第三十一节 二叉树进阶的一些面试题(二)
(中序和后序跟前序的思路完全一 致,只是前序先访问根还是后访问根的问题。后序稍微麻烦- -些,因为后序遍历的顺序是左子树右子树根,当取到左路结点的右子树时,需要想办法标记判断右子树是否访问过了,如果访问过了,就直接访问根,如果访问过需要先访问右子树。这里访问右子树要以循环从栈依次取出这些结点,循环子问题的思想访问左路结点的右子树。这题是上面那题的姊妹题,换换顺序就能写好了。但是这道题我们的目的是用迭代做出来。2.再访问左路结点的右子树。原创 2024-08-19 01:06:27 · 207 阅读 · 0 评论 -
[C++进阶]第三十节 二叉树进阶的一些面试题(一)
核心思想:我们在层序遍历过程中,增加一-个levelSize,记录每层的数据个数,树不为空的情况下,第1层levelSize=1,循环控制,第1层出完了,第2层就都进队列了,队列中size就是第2层的数据个数。这道题属于与基础题,首先我们观察输入输出样例可以得到如果root->left为空,root->right不为空时,我们的空格仍然需要保留,如果当前节点有两个孩子,那我们在递归时,需要在两个孩子的结果外都加上一层括号;上题我们搞完了,这题我们其实有个很简单的办法,我们把上题的代码赋值过来直接逆置即可。原创 2024-08-18 00:56:30 · 407 阅读 · 0 评论 -
[C++进阶]第二十九节 二叉搜索树的应用
前面我们讲过key模型和Key-Value模型就是常见的两种的模型。原创 2024-08-16 16:54:02 · 435 阅读 · 0 评论 -
[C++进阶&数据结构]第二十八节 二叉搜索树
对于二叉树的结点,我们类似于list的结点定义一样,使用一个struct类。原创 2024-08-07 10:53:46 · 1418 阅读 · 0 评论 -
[C++进阶]第二十七节 继承和多态的选择题
子类定义的虚函数的新的行为会操作a变量,在子类初始化时根据构造函数调用顺序会首先调用父类构造函数,那么虚函数回去操作a,而因为a是子类成员变量,这时a尚未初始化,这是一种危险的行为,作为一种明智的选择应该禁止这种行为。C. 选择题一定要扣字眼,题目前半句说的是基类引用 引用了子类对象,但是后半句调用虚函数时,说的是基类的对象调用f2,通过对象调用时编译期间就直接确定调用那个函数了,不会通过虚表以多态方式调用。C.A::f(),因为强制类型转化后,生成一个基类的临时对象,pa实际指向的是一个基类的临时对象。原创 2024-07-31 01:31:09 · 890 阅读 · 0 评论 -
[C++进阶]第二十六节 抽象类
在虚函数的后面写上 =0 ,则这个函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象。派生类继承后也不能实例化出对象,只有重写纯虚函数,派生类才能实例化出对象。纯虚函数规范了派生类必须重写,另外纯虚函数更体现出了接口继承。至于为什么起这个抽象的名字,我们可以理解为,这个类在现实世界中没有实体。所以不能实例化出对象。而且由于派生类继承了抽象类,它里面也包含了纯虚函数,那么它自然也不能实例化出对象了。原创 2024-07-29 08:42:26 · 421 阅读 · 0 评论 -
[C++进阶]第二十五节 对于多态的底层逻辑
在前面我们也已经提到过,在语法层面称之为重写,重写的是它的实现。所以有时候我们也会提出一个概念,普通的函数的继承称为实现继承,而多态,虚函数的重写,其实就是一个接口继承,然后重写它的实现在原理上就是说将父类的虚函数表给拷贝下来,然后将子类中重写的部分给覆盖。其次,因为只有完成了虚函数的重写,那派生类的虚表里面才能是派生类的虚函数。这样的话,这个基类指针才能做到指向父类调用父类,指向子类调用子类。原创 2024-07-29 00:00:14 · 1188 阅读 · 0 评论 -
[C++进阶]第二十四节 多态的概念、定义与实现
多态是在不同继承关系的类对象,去调用同一函数,产生了不同的行为。比如Student继承了Person。Person对象买票全价,Student对象买票半价。那么在继承中要构成多态还有两个条件:必须通过基类的指针或者引用调用虚函数被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写。多态的实现有两个条件必须通过基类的指针或者引用调用虚函数被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写(也就是要调用重写的虚函数)。原创 2024-07-26 01:11:34 · 1038 阅读 · 0 评论 -
[C++进阶]第二十三节 多继承和菱形继承
很多人说C++语法复杂,其实多继承就是一个体现。有了多继承,就存在菱形继承,有了菱形继承就有菱形虚拟继承,底层实现就很复杂。所以一般不建议设计出多继承,一定不要设计出菱形继承。否则在复杂度及性能上都有问题。多继承可以认为是C++的缺陷之一,很多后来的OO(OO是面向对象,OOP是面向对象程序设计)语言都没有多继承,如Java。原创 2024-07-23 00:25:45 · 797 阅读 · 0 评论 -
[C++进阶]第二十二节 继承
Person类称为基类(父类),Student类称为派生类(子类)继承方式为public(公有)继承。原创 2024-07-22 17:03:05 · 711 阅读 · 0 评论 -
[C++进阶]第二十一节 模板进阶
class 类模板名 {};T* _finish;原创 2024-07-21 23:04:39 · 1162 阅读 · 2 评论 -
[C++]第二十节 优先级队列
优先级队列是一种容器适配器,根据一些严格的弱排序标准,专门设计使其第一个元素始终是它所包含的元素中最大的元素。此上下文类似于堆,其中可以随时插入元素,并且只能检索最大堆元素(优先级队列中顶部的元素)。优先级队列是作为容器适配器实现的,容器适配器是使用特定容器类的封装对象作为其底层容器的类,提供一组特定的成员函数来访问其元素。元素是从特定容器的“背面”弹出的,该容器称为优先级队列的顶部。基础容器可以是任何标准容器类模板,也可以是其他一些专门设计的容器类。原创 2024-07-19 23:27:54 · 1197 阅读 · 0 评论 -
[C++初阶]第十九节 deque的讲解
Deque是双端队列的不规则缩写。双端队列是具有动态大小的序列容器,可以在两端扩展或收缩。特定的库可能以不同的方式实现deque,通常是某种形式的动态数组。在任何情况下,它们都允许通过随机访问迭代器直接访问单个元素,并根据需要通过扩展和收缩容器来自动处理存储。因此,它们提供了类似于向量的功能,但在序列的开始,而不仅仅是在序列的末尾,也可以有效地插入和删除元素。但是,与vector不同,deque不能保证将其所有元素存储在连续的存储位置:通过偏移指向另一个元素的指针来访问deque中的元素会导致未定义的行为。原创 2024-07-19 01:14:44 · 985 阅读 · 0 评论 -
[C++]第十八节 一些list,stack和queue选择题和编程题
这时我们学完后的应用1.下面有关vector和list的区别,描述错误的是( )A.vector拥有一段连续的内存空间,因此支持随机存取,如果需要高效的随机存取,应该使用vectorB.list拥有一段不连续的内存空间,如果需要大量的插入和删除,应该使用listC.vector::iterator支持“+”、“+=”、“原创 2024-07-16 23:17:36 · 1036 阅读 · 0 评论 -
[C++]第十七节 reverse_iterator的封装实现
反向迭代器适配器(reverse_iterator),可简称为反向迭代器或逆向迭代器,常用来对容器进行反向遍历,即从容器中存储的最后一个元素开始,一直遍历到第一个元素。值得一提的是,反向迭代器底层可以选用双向迭代器或者随机访问迭代器作为其基础迭代器。当反向迭代器执行 ++ 运算时,底层的基础迭代器实则在执行 -- 操作,意味着反向迭代器在反向遍历容器;当反向迭代器执行 -- 运算时,底层的基础迭代器实则在执行 ++ 操作,意味着反向迭代器在正向遍历容器。原创 2024-07-16 15:01:59 · 245 阅读 · 0 评论 -
[c++初阶]第十六节 stack和queue的使用以及模拟实现
区别于vector等容器,stack是一种容器适配器。通俗的讲,stack封装了一个其他的容器,并提供特定的成员函数来对容器进行操作并遵循栈的后进先出(Last-in First-out)原则。stack的底层容器至少要支持以下操作:empty:判空size:获取容器有效元素个数back:获取容器尾部元素push_back:尾插pop_back:尾删通过这些操作,我们就可以实现栈的压入和弹出等行为。原创 2024-07-16 00:57:50 · 934 阅读 · 0 评论 -
[C++初阶]第十五节 list的模拟实现
首先,我们一开始最先看到的就是这个结点的结构体,在这里我们可以注意到这是一个双向链表。有一个前驱指针,一个后继指针。然后在有一个存储数据的空间其次它的迭代器是一个自定义类型,而非原生指针。这里我们先不管,我们接着往下看。我们继续找成员变量,在这里我们就找到了成员变量,但是这个类型我们看不懂,于是我们先略过。通过对定义的查找,可以看到这个实际上还是一个指针。但是这个指针我们还是看不懂。于是我们继续去速览定义,于是就找到了这里。原创 2024-07-14 20:21:37 · 1375 阅读 · 0 评论 -
[C++初阶]第十四节 list类的初步理解
并且在C++文档中,我们可以看到标准库中的sort也限定了迭代器的类型必须是可以进行随机访问(RandomAccess)的。实际上list的迭代器并不是用原生态指针进行模拟实现的,需要进行底层的封装,这里会在list的模拟实现的源代码中体现。但是list的删除操作一定会导致迭代器失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。list由于结构的特殊性,是无法使用标准库中的sort函数的,因为迭代器无法进行相减的操作。(请注意,此函数通过插入或擦除容器中的元素来更改容器的实际内容。原创 2024-07-10 10:59:08 · 1023 阅读 · 0 评论 -
[C++初阶]第十三节 vector的模拟实现
上篇我们实现了STL学习的三步:能用,明理,能扩展中的能用,着篇我们要办到明理。所以,本篇,我们将会对于vector进行模拟实现。这里我们采用和之前一样的方法自己开一个命名空间,写出我们自己的vector类像这样。原创 2024-07-06 00:28:34 · 963 阅读 · 0 评论 -
[C++初阶]第十二节番外 vector的oj
将快指针 fast 依次遍历从 1 到 n−1 的每个位置,对于每个位置,如果 nums[fast]=nums[fast−1],说明 nums[fast] 和之前的元素都不同,因此将 nums[fast] 的值复制到 nums[slow],然后将 slow 的值加 1,即指向下一个位置。由于给定的数组 nums 是有序的,因此对于任意 i原创 2024-07-08 20:36:04 · 798 阅读 · 0 评论 -
[C++]番外 迭代器失效
如果pos刚好对应最后一个元素,删除后迭代器pos就超出了有效元素范围,可能导致非法访问,属于迭代器失效。以上函数在使用时都可能会导致vector扩容,在扩容时原空间会被释放,迭代器就会指向一块被释放的空间。假设有迭代器pos,使用pos删除pos对应位置的元素后,该迭代器对应的元素发生改变,属于迭代器失效。当迭代器底层的指针指向的空间被销毁时,如果继续在程序中使用该迭代器,就会造成程序崩溃,这就是。迭代器失效后,如果我们需要继续使用迭代器,给迭代器重新赋值即可。本篇是对于vector的那篇章的补充。原创 2024-07-04 16:48:52 · 207 阅读 · 0 评论 -
[C++初阶]第十二节 vector的初步理解
1. vector是表示可变大小数组的序列容器和数组一样,vector可采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。2. 本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小,以增加存储空间。其做法是:分配一个新的数组,然后将全部元素移到这个数组。原创 2024-07-04 00:56:58 · 1227 阅读 · 0 评论 -
[C++初阶]第十一节 string类的详解
//string.cpp现在我们看到的是,我这边写的,接下来我将会对于这些内容进行解析,首先我这边的模拟实现都是基于理解和string。 2.string类的定义和迭代器1)私有成员这里的内容比较少。2)公有成员3)迭代器我们都知道在string中我们常常使用迭代器来完成不少操作,我们知道迭代器其实就是一种指针,所以这里我们选择这样实现3.构造函数声明:这里我们选择用缺省函数保证字符串内容下面是搞函数的内部实现:首先我们用列表初始化得出原创 2024-06-09 14:32:05 · 914 阅读 · 0 评论 -
[C++初阶]第十节番外 string的几道oj题
然后我们把它尾插入我们创建的新的string中(这里我选择采用尾插,但也可以用头插(但是头插的时间复杂度更高,因为每次头插都要移动位置))同时我们一块定义好我们的进位值,因为我们进行的是10进制计算。注意:我们要判断是否超过了int的最大值或最小值,而且要保证自己的int类型不超过int的最大值或最小值。如果超出了最值,我们接下来通过symbol的值来判断是最大值还是最小值,然后返回相应结果。如果读完了所有的数,都没有超出最值,那么我们直接调用上面我们写的公式返回。判断此时读入的是否为数字,是数字则读入。原创 2024-05-08 21:44:19 · 1076 阅读 · 6 评论 -
[C++初阶]第十节 string类
nposnpos的值通常是一个很大的正数,等于-1(当作为无符号数解释时或等于string::size_type的最大可能值。原创 2024-05-04 12:38:59 · 1103 阅读 · 6 评论 -
[C++初阶]第九节 STL的介绍
STL是C++编程语言中的一个重要组成部分,它提供了一系列标准化的模板类和函数,旨在简化程序设计,提高代码的复用性和可维护性。4. STL的使用会有代码膨胀的问题,比如使用vector/vector/vector这样会生成多份代码,当然这是模板语法本身导致的。STL的设计思想是将数据结构和算法分离,这样可以灵活地将不同的算法应用于不同的数据结构上,从而提高编程效率和代码的可读性。中的优秀作品,有了它的陪伴,许多底层的数据结构以及算法都不需要自己重新造轮子,站在前人的肩膀上,健步如飞的快速开发。原创 2024-04-30 19:46:02 · 332 阅读 · 5 评论 -
[C++初阶]第八节 模板初阶
函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。1. 重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增加对应的函数。函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定。如果类型不匹配,编译器会尝试进行隐式类型转换,如果无法转换成功编译器将会报错。巧的是前人早已将树栽好,我们只需在此乘凉。2. 代码的可维护性比较低,一个出错可能所有的重载均出错。,对于字符类型也是如此。,对于模板函数的使用,原创 2024-04-26 22:20:49 · 332 阅读 · 6 评论 -
[C++初阶]第七节番外 内存管理的几道选择题
分析:首先手动释放pa, 所以会先调用A的析构函数,其次会跟定义相反的顺序释放局部对象,这里只有b,就释放b,再释放静态局部对象d,再释放全局对象c。A.栈区主要存在局部变量和函数参数,其空间的管理由编译器自动完成,无需手动控制,堆区是自己申请的空间,在不需 要时需要手动释放。B.new 初始化对象,调用对象的构造函数,对应的delete调用相应的析构函数,malloc仅仅分配内存,free仅仅回收内存。B.栈区先定义的变量放到栈底,地址高,后定义的变量放到栈顶,地址低,因此是向下生长的,堆区则相反。原创 2024-05-04 19:09:50 · 445 阅读 · 4 评论 -
[C++初阶]第七节 C++内存管理
如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是:new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常, malloc会返回NULL。申请空间失败, 尝试执行空间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。,如果malloc申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛异常。2. 在申请的空间上执行N次构造函数。原创 2024-04-26 20:40:51 · 1004 阅读 · 2 评论 -
[C++初阶]第六节番外 一些类的选择题
A.友元函数不是类的成员函数,就相当于你的朋友再亲密也不是你的家人,既然不是类成员函数,那和普通成员函数调用一样,不需要通过对象调用。A.初始化顺序由定义类时的声明顺序决定,所以先初始化_a2,由于初始化_a2时_a1还未初始化,所以为随机值,故错误。B.友元的目的就是为了访问类的私有数据,成员函数可以直接访问类的私有数据。B.友元函数和类的成员函数都可以访问类的私有成员变量或者是成员函数。C.类的成员函数是属于类的,调用的时候是通过指针this调用的。6.下面有关友元函数与成员函数的区别,描述错误的是?原创 2024-04-25 22:34:44 · 372 阅读 · 4 评论 -
[C++初阶]第六节 日期类
前面我们讲过了类和对象,现在我们来建立一个日期类来实践一下吧。原创 2024-04-25 16:02:14 · 816 阅读 · 8 评论 -
[C++初阶]第五节 类和对象(三)
类是对某一类实体(对象)来进行描述的,描述该对象具有那些属性,那些方法,描述完成后就形成了一种新的自定义类型,才用该自定义类型就可以实例化具体的对象。原创 2024-04-22 20:54:21 · 1233 阅读 · 10 评论 -
[C++]第四节 类和对象(二)
而_t是Time类对象,所以在d销毁时,要将其内部包含的Time类的_t对象销毁,所以要调用Time类的析构函数。但是,main函数中不能直接调用Time类的析构函数,实际要释放的是Date类对象,所以编译器会调用Date类的析构函数,而Date没有显式提供,则编译器会给Date类生成一个默认的析构函数,目的是在其内部调用Time类的析构函数,即当Date对象销毁时,要保证其内部每个自定义对象都可以正确销毁main函数中并没有直接调用Time类析构函数,而是显式调用编译器为Date类生成的默认析构函数。原创 2024-04-21 21:33:32 · 1030 阅读 · 10 评论 -
[C++初阶]第三节 类和对象(一)
1. 声明和定义全部放在类体中,需注意:成员函数如果。原创 2024-04-16 13:54:23 · 899 阅读 · 12 评论 -
[C++初阶]第二节 初识C++(二)
引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。我们可以举个例子:比如:李逵,在家称为"铁牛",江湖上人称"黑旋风"。铁牛,黑旋风,都是李逵的别名。写法是用&符号修饰,类型& 引用变量名(对象名) = 引用实体;原创 2024-04-06 00:03:25 · 791 阅读 · 2 评论