- 博客(80)
- 收藏
- 关注
原创 Linux指令:
我们今天来学习一下linux的一些相关的指令L:pwd指令表示的是我当前在哪条路径下;我当前在哪里;我们看这个第二句话,因为在windows环境下,当我们登录进入到我们的电脑的时候,我们会首先进入到我们的桌面,但是其实,这个桌面其实是一个文件,是存储在C盘的用户里面的一个文件,但是这个文件比较重要,我们就把他进行图形化界面放到了我们的桌面,所以说,我们的桌面实际上也是一个文件。我们的第二条指令“whoami”表示的是现在是谁在访问Linux系统;我们有时候写了很多的指令的时候,电脑屏幕上会有很多的指令执行的
2025-06-02 14:54:23
787
原创 C++11(2):
我们今天接着讲C++11的内容,在讲新的内容之前,我们先回顾一下我们之前许过的内容,我们上节课学习了右值引用和移动语义:我们说右值的生命周期只有一行,这行结束以后,右值的生命周期就结束了,这里的话,我们可以把右值比喻成一个身体不好生命快要结束的人,左值的话我们可以比喻为身体健康,生命不会很快的结束的人。所以对于深拷贝的类型的话,我们就可以增加一个右值引用的移动构造和移动赋值,之前的话,我们走的都是左值的拷贝构造和拷贝赋值,我们实现的函数参数是const 修饰的左值,这样的话我们的右值也可以走这条路,。但是现
2025-05-25 12:12:47
642
原创 哈希表(2):
之前我们使用开放定址法实现的,我们现在使用链地址法来实现,这两种方法都可以,我们就使用namespace把之前的方法封装起来。那我们插入数据到一个哈希桶里面的时候,我们是头插还是尾插呢?插入结点的话,那就要分情况了,哈希表可能为空,也可能不为空;//这两种都是库里面有的,我们是自己实现一下。这个就是我们的普通的insert函数的实现。如果有说是哈希表的某一个桶很长的话,首先我们看这个插入函数,那我们的扩容要怎么扩呢?
2025-05-17 21:10:23
721
原创 哈希表实现(1):
直接定址法是我们设置哈希函数的第一种方法:直接定址法的限制就是适用范围比较集中的时候,如果范围不集中的话,我们就不能使用直接定址法。
2025-05-16 20:40:30
1161
1
原创 每日练习:
今天是学习算法的第二天:依旧是每日练习奥兄弟们:首先是第一题:我们来分析一下这个题目;这里有两个例子,一个是19,经过这个快乐循环最后是可以得到1的,但是数字2的话,他是会进行无限循环的。这两个例子都可以抽象成这样来看,这样的看的话,我们是不是就比较熟悉,我们讲解数据结构的时候,有一个题目的要求是判断链表是否有环,我们看,当我们的数据是我们的快乐数的时候,我们的环里面的数据就都是1,但是如果我们传进来的这个数据不是我们的快乐数,我们的环里面的数据都是不相同的。我们之前判断链表里面是否有环的时候,我们可以使用
2025-05-14 16:41:33
372
原创 unordered_map和unordered_set:
今天我们来学习一下unordered_map和unorder_set,这两个容器是我们哈希相关的容器;这两个数据结构的底层是哈希;我们先看一下他们的使用:我们今天讲他们的使用的话,会讲的比较快,因为他们和之前的使用几乎是一样的。他们的功能基本上是高度相似的。当然他们也都有普通的版本和multiset版本。这个查找的效率unordered_set的效率非常快。
2025-05-13 13:20:06
404
原创 红黑树():
红黑树从根节点开始的最长的路径不会超过最短路径的2倍。红黑树的话,他的结点的分布没有我们的AVL树的结点的分布均衡,但是效率也不错,AVL树的结点分布的那么均匀,其实也是在进行了旋转,付出了代价换来的绝对的均衡。那么红黑树的“红黑树从根节点开始的最长的路径不会超过最短路径的2倍”是怎么被维持的呢?这两个是我们的红黑树,第一个红黑树的左边全黑的路径就是最短路径,右边一黑一红的是最长的路径,最长路径<=最短路径的2倍;那我们来数一下我们的这两个红黑树的路径有多少跳呢?我们的第一个红黑树的路径有8条,第二个有10
2025-05-10 16:56:33
995
1
原创 AVL树(2):
我们之前讲AVL树,我们讲到了旋转,然后讲了左单旋和右单旋。但是我们这里的单旋产生的条件都是纯粹的一边比较高,我们看上面这个图片,当我们插入新的结点导致一边的子树比较高的时候,我们必须是存粹的一边高,和图片上面的几个一样,图片下面的几个就不行。我们看图片中下面的,当我们插入一个结点,结点里面的key(可能是存单个数据的搜索二叉树set,也可能是存一对数据的搜索二叉树,但是维持我们的搜索二叉树的本质的还是要看我们的key)比我们的5大的时候,这时候我们把他插入到我们的5结点的右子树的位置上。这时候他就不是我们
2025-05-04 23:30:09
5813
原创 多态():
这里我们看概念,里面引入了一个虚函数,这个就要引入一个关键字virtual;这个virtual是我们上节讲的,为了避免我们的菱形继承的数据冗余和二义性;但是在这里他们两个没有什么关联,我们这里说我们的虚函数,我们在我们的成员函数的前面加上virtual,这个函数就是虚函数。我们说我们实现动态多态的条件之一就是:被调⽤的函数必须是虚函数,并且完成了虚函数重写/覆盖。我们说虚函数的覆盖就是我们图中的这个,在派生类和基类里面有一个函数名,参数,返回值都相同的函数。,,三同。
2025-04-23 00:36:09
551
原创 继承(2):
我们继续接着上一节的来讲:我们之前学习了四个常见的默认构造,我们今天继续来看:对于我们的派生类的构造函数:当我们初始化我们的派生类的时候,我们的派生类的自己的那部分,我们就正常的构造函数里面初始化,然后我们的派生类里面的基类的那部分,我们要调用我们的基类的构造函数来进行初始化。我们看这个图片,我们的派生类的构造函数的书写:我们写这个类的构造函数的时候,初始化我们的基类的时候,会调用我们的基类的默认构造来初始化我们的派生类继承下来的基类的那部分。如果有默认构造的话,我们可以直接不管。如果基类没有默认构造的话,
2025-04-20 14:27:59
825
原创 继承:(开始C++的进阶)
我们今天来学习C++的进阶:面向对象三大特性:封装,继承,多态。封装我们在前面已经学了,我们细细理解,我们的类的封装,迭代器的封装(vector的迭代器可以是他的原生指针,list迭代器不能是他的原生指针,我们进行封装),适配器的封装(stack和queue的封装)。我们今天就来学习他的第二大特性:继承;
2025-04-16 23:41:17
1322
原创 模板进阶:
我们定义了栈的类,我们定义的这个栈是静态的栈。现在我们的要求是实例化两个类,这两个类的大小要求不一样,但是你看我们的这个代码,我们定义了一个宏,来代表我们的数组的大小,但是我们的要求是两个数组大小不一样,我们这样得到的是两个大小相同的数组,,似乎我们根本控制不了这两个静态的栈的大小不一样。这时候我们就要学习一下:非类型模板参数:我们看这个代码,我们的这个代码,我们定义模板的时候,我们定义了一个新的模板参数,这个新的模板参数他不是class类型的,这个就是我们的非类型模板参数。我们有了这个参数,我们就可以实例
2025-04-16 13:41:13
1006
原创 优先级队列(堆二叉树)底层的实现:
我们继续来看我们的优先级队列:优先级队列我们说过,他也是一个容器适配器,要依赖我们的容器来存储数据;他的第二个参数就是我们的容器,这个容器的默认的缺省值是vector,然后他的第三个参数,我们上节讲到,他的top和pop接口都是按照优先级的顺序来进行去取的,然后我们的优先级顺序默认的是大的优先级比较高,这里有一个比较坑的点,那就是我们如果想让大的数据优先级高的话,我们可以直接不传,他的默认的缺省值就是大的优先级高,这个缺省值就是less,然后我们如果想让小的数据的优先级高的话,我们就传greater,是的,
2025-04-14 21:02:31
994
原创 Stack和Queue容器适配器:
使用我们的优先级队列的话,我们直接包含queue的头文件就可以了,我们的优先级队列也包含在里面了。我们的优先级队列也是一个容器适配器,我们的第二个传过来的容器的缺省值是我们的vector<T>;我们这里不使用deque来作为缺省值,他的方括号[]的效率没有vector高。我们这里的接口top和pop比较特殊,我们的top取数据,取的是优先级高的,pop接口,删除的是优先级低的数据。我们这里打印出来的结果是: 6 5 5 2 1;
2025-04-12 00:32:33
886
原创 list:
我们看这个代码,假设我们现在想让一个链表的最后面的数据放到我们的最开始的位置,我们也可以使用这个splice接口。(我们的上面的end(),这个接口是我们的最后一个数据的下一个位置,也就是空)。第一种是把一个list里面的数据粘接到新的list里面,第二个参数是要粘接的list的别名,第一个参数表示要粘接的位置,把list粘接到position位置的前面。list里面的sort函数的效率比较低下;我们再看一下这个图片,我们的list里面的迭代器是双向的迭代器,根本满足不了我们的算法库里面的参数类型。
2025-04-06 15:48:58
692
原创 vector的实现:
我们接着来看:我们看我们的扩容reserve的函数接口:我们的这个函数接口也不太对。我们的这个类我们实现的是一个模板类,里面的T是什么类型的我们不知道,他可能是int类型之类的内置类型,也可能是自定义的类型,这个时候我们的扩容的函数里面的扩容方式是memcpy拷贝,我们看下面的图片:我们看这个图片,
2025-04-04 19:02:57
715
原创 vector:
我们之前学习并且实现了我们的容器string。我们今天来学习我们STL的第二个容器:vector,我们的这个容器表示的是我们的顺序表。我们看一下我们的vector,当我们打开vector的时候我们看这个容器的接口,这个接口和我们的string是比较类似的,都是STL,接口差不多,我们看起来都比较熟悉,讲起来也会快很多。
2025-03-29 15:26:51
947
原创 string的实现:
我们之前学习了string,也知道了string的几个接口,我们今天来自己来实现一下string我们自己来实现我们的string,我们当然是要把他的接口全部实现了。这个代码已经实现好了,这个讲的比较清晰。//这个是实现好的代码,可以参考。
2025-03-27 00:32:20
319
原创 string的接口讲解:
我们的size()接口返回的是我们的元素的个数,我们的length()返回的是我们的字符串的长度;当然,我们的库里面已经重载了我们的输出的流,我们的这个作用也就不大了,但是对于我们自己实现类string的时候,我们一开始没有重载流,我们就可以使用这个来输出我们的对象里面的字符串。我们看上面的图片,我们在最开始的位置加上我们的头文件和我们的namespace std,这个名字空间,我们的string包含在我们的std库里面。我们看这个图片:我们首先把我们的扩容的接口函数屏蔽掉;我们这时候要介绍一个+=接口;
2025-03-25 13:27:30
850
原创 string(1):
我们今天开始学习STL,我们的string是我们的STL里面的一个容器类。我们的C++含有许多的库:有STL,也有其他的库。
2025-03-19 17:38:23
670
原创 内存管理:
我们的realloc扩容分为两种,一种是原地的进行扩容,还有一种是异地的扩容,我们看我们的原地扩容,我们的原地扩容是在我们的原本的内存的后面是有满足我们要求的内存的大小的,这时候我们就直接扩容,扩容后我们的p3指向我们的这块内存,但是我们的p2也是指向我们的这块内存的,这时候两个指针指向同一块内存区域,我们只要把他释放一次就够了,至于我们的指针,我们出了函数以后,我们的指针存在于栈区的,他就被销毁了。我们的realloc函数的参数,第一个是我们要进行扩容的对象的指针,第二个参数是扩容后我们的数组的大小。
2025-03-16 22:21:13
944
原创 类和对象:
不行的,我们的缺省值是要给我们在初始化列表里面进行初始化的那些成员变量,我们的静态的成员变量他就不是在我们的初始化列表里面初始化的,他是在我们的类的外面进行初始化的,这里我们就不能给他缺省值。我们看下面的图片,当我们有两个类的时候,我们的B类里面的成员函数想要使用我们的A类里面的成员变量,这时候我们可以把B设置成我们的A类的友元类,我们看这个代码,我们的这个代码我们测量一下我们的类A的大小,这时候我们测出来的结果是4个字节,我们看我们的这个代码:之前我们在调用我们的成员函数的时候。
2025-03-15 20:59:07
558
原创 类和对象:
这个就是我们的赋值运算符的重载,我们来分析一下这个代码,我们的成员函数,我们的d1传给this指针,然后d2传到形参d,然后我们把d2的值赋给d1,最后的话,我们返回我们的d1,因为我们想要实现连续赋值,这时候我们的函数就必须要有返回值,我们把我们的this指针指向的对象进行返回,但是我们这里的返回类型,我们建议使用引用返回,当然我们的传值返回也可以满足我们的要求,但是我们的传值返回就需要进行拷贝构造,这就还是开销,但是我们使用引用返回的话,这时候就更方便了。我们的第四行,我们的d5对象是刚开始实例化。
2025-03-12 11:58:09
397
原创 C++入门再补充:
我们今天主要是来讲解我们的类和对象;但是我们的上一节课我们的C++入门还有部分没有讲完,我们今天就先把他们讲完吧。我们之前讲了内联inline。
2025-03-06 13:34:49
814
原创 C++入门续集:
我们的指针和引用在大部分的功能上是重叠的。引用其实就是取别名;给我们已有的变量取一个别名;取别名我们可以见到很多案例,比如林冲我们还可以叫他豹子头。那我们在这里怎样给我们的变量取别名呢?类型 + & + 引用别名 = 引用对象;在这里我们就是给a取了一个别名b。当然我们也可以给我们的别名再取一个别名,我们给我们的b取别名为d。我们在这里继续看,我们给d++以后,a,b,c都要++,他们几个本质上都是一个东西。然后我们还把他们的地址打印出来,他们的地址都是一样的。
2025-03-04 23:32:14
334
原创 C++入门
那么namespace该怎么使用呢?我们来看这个,我们创造一个namespace,bit,我们可以把我们的变量,函数,结构体,,,都可以放进去,我们的namespace其实就是一个新的域,我们的不同的域我们是可以创造相同的名字的函数的,我们的全局变量和我们的局部的变量的变量的名字是可以一样的,但是他们同时存在的时候,我们的局部变量要优先,。我们的namespace是在全局里面定义的,所以namespace里面的函数的生命周期是全局的,他是在了一个新的域。
2025-03-01 20:00:35
844
原创 排序算法(3):
那么我们该怎么创造我们的数组呢?跟上面的一样取出数组里面的最大值然后+1,创造一个这么大的数组吗?我们来看下面的情况:我们来看这个图片,这次我们要排的数据是100到109,这时候我们能取他的最大值然后 +1吗?我们要创造110个空间,但是我们的数组里面最小的数据为100,这就会导致前面下标(0--99)100个空间被浪费掉,这样的话损耗是比较大的,那我们怎么办呢?我们就在数组里面找到最大的数据,再找到最小的数据,最小的数据,所以这时候我们的数组的空间的大小就是最大的数据 - 最小的数据 + 1。
2025-02-26 23:20:57
991
原创 二叉树--链式存储
1我们之前学了二叉树的顺序存储(这种顺序存储的二叉树被称为堆),我们今天来学习一下二叉树的链式存储:我们使用链表来表示一颗二叉树:⽤链表来表⽰⼀棵⼆叉树,即⽤链来指⽰元素的逻辑关系。通常的⽅法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别⽤来给出该结点左孩⼦和右孩⼦所在的链结点的存储地址。比如这就是我们的二叉树的链式存储,跟链表是不是比较像,就是使用链表来进行存储我们的二叉树;但是我想你也一定发现了我们使用链式存储的二叉树不一定是完全的二叉树;
2025-02-03 23:55:41
1010
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人