- 博客(35)
- 收藏
- 关注
原创 c++11的学习
右值的引用它的本质上是左值,为什么呢,就拿移动拷贝来说 我们要举行swap转换,用swap转换各自的资源,右值一般是临时对象,常量,都具有const的性质,如果右值引用本质是右值,那么我们如何用swap来转换资源呢?完美转化:我们用了引用折叠,那么我们再次调用别的函数的时候,就像上面,假如是右值,传参的时候匹配到了左值该怎么办,我们就要用forwar函数,让他自动识别帮助我们传参。2.2 decltype 和auto 有点类似,也可以进行推到数据类型,主要的是将变量的类型声明为。
2024-08-29 13:27:22
777
原创 红黑树的学习
在计算路径黑色结点个数的时候,我们可以检查到红结点的时候,判断它的父亲是不是也是红色,如果从父亲判断孩子的话,有两个孩子,还需要判断空指针问题,不如判断父亲的颜色,因为根是黑色的,不用担心他被访问父亲。如果每次插入是黑色结点,我都得协调每条路径的黑色结点,如果是红色,我只需要考虑,它的父亲是不是红色结点,在进行调色。第一种:叔叔(父亲的兄弟结点,也就是父亲的父亲,它的除了父亲的孩子)存在且为红色结点,那么我们就需要把叔叔和父亲一起调成黑色,接着再往上调整父亲的父亲的结点颜色。旋转就不用再往上改颜色了。
2024-08-21 02:04:41
490
原创 AVL树的学习
就又成为了应该刚才右旋的,因为此时的平衡因子是-2 和-2.总结一下,就是失衡的结点再次成为parent ,然后parent的left要往下转,也就是左旋,然后成为它右孩子的子结点,也就是成为parent->left->right的子结点,正好对应了LR型,然后进行右旋,,也就是形成该样子,把平衡因子为2的14结点向下转,也就是右旋,转成六结点的右孩子,然后6的右孩子,就成了14的左孩子,6的右孩子是空也无妨。我们再代码区域看到了,我已经进行了平衡因子的更新,接下来我们说一下单旋的平衡因子是怎么更新的。
2024-08-18 01:00:58
846
原创 map和set
insert的返回值是一个pai<iterator,bool>,我们可以通过first和second来访问,而且此时的insert是一种搜索功能的,也就是我们插入的时候,会检查有没有重复的,如果有重复的bool值就会成false,没有重复的就插入成功。因为map的【】是用insert进行底层的,所以它的返回值也是一个pair,再通过对pair的解引用就访问到了修改 ,所以我们可以通过对map的第一个key寻找,就能找到了对应的second。
2024-08-16 01:09:23
708
原创 string 的完整介绍
在数组中,我们可以通过[下标]访问数组内容,在c++中,string进行了运算符重载,[]也可以访问string,但是这个运算符重载,多了一项功能,就是帮助我们检查我们访问的下标大不大于我们的sz,就是字符串长度。另外要提一嘴的就是,我们人类的语言与计算机的语言不一样,所以美国发明了ASCLL码表,这样计算机就能我们输入的东西是什么,记着就有各种的字符编码,有unicode,gbk等等,仅作了解。还记得我们数据结构学的串吗,现在在c++中,我们有了c++提供的标准库,它是一个写好的类,非常方便使用。
2024-07-13 22:32:47
829
原创 c++的模板简单介绍
我们就用栈来举例子,为什么要又类模板呢,加入我们想存int的,又想存double的,我们是不是得创建两个栈啊,所以我们写成模板,这样方便形成。还有一种写法,我们还学过auto,这个就会自动帮助我们推算类型,所以我们写两个类型,去接受,让编译器帮助我们去推算。可是最后一条,这是让编译器怎么计算呢,是转换成double呢还是int呢,这时候我们的实例化就要起作用了,告诉编译器我们需要的推算类型。我们来简单举个例子。就是Swap函数的例子,相信大家已经对这个已经不陌生了,我们用模板的方式来写一下。
2024-07-04 01:41:28
405
原创 c++内存管理
new(aa1)A 这句代码是什么呢,这就是调用构造函数,就像上边我们画的图那样,需要调用构造函数,但是构造函数不能像析构函数那样显示调用,c++的写法就是new(地址)类型(含参构造)隐式类型转换.aa1调用析构函数给它里面申请的空间释放了,然后再用 operator new来释放aa1。这里需要注意的是,“abcd”刚才我们不是说了在代码段吗,现在怎么在栈上了,原因是将常量区的数据拷贝了一份,放在了栈上,也就是char2刚才在栈开辟的空间。a是属于栈上的,它属于具有变量,abcd是在代码段的。
2024-07-03 02:37:42
611
原创 类与对象完结
我们这么定义匿名对象,匿名对象的特点不用取名字, 但是他的生命周期只有这一行,我们可以看到下一行他就会自动调用析构函数。aa1就是就是有名类,如果我们直接给一个类进行构造就是匿名类。
2024-07-02 21:25:39
191
原创 类与对象(4)
此时我们看一下对类A的一些操作,前两个没什么好说的,第三个我们看,直接把3给A了,int给自定义类型,这是什么情况,其实这是隐式类型的转换。当 _scount是静态区的成员时,不在类的里面,当我们每个类的创建时候都会进行调用构造函数或者拷贝构造函数,所以我们只要知道_scount的值就会知道有多个类。第四个是因为,隐式类型转换的时候具有常性(类型转换就有临时对象的产生,比如double转int),所以引用的时候,权限不可以放大,要加const。如果C是B的友元, B是A的友元,则不能说明C时A的友元。
2024-07-02 01:07:26
388
原创 类与对象(3)
值得注意的是我们的+=用的引用返回,但是+用的就是传值返回,+=的对象一直在类里面没有因为+=函数结束而销毁,所以用引用返回没问题,但是我们+用的是一个局部变量,会销毁,但是如果传值返回我们会形成一个临时对象的拷贝,所以我们防止计算出的结果的销毁,用传值返回,保证值的成功返回。其次我们看下面这个,为什么返回这个可以呢,因为传值返回是返回 它的拷贝的临时对象,就是d要先调用一下拷贝构造,然后接着呢,再把拷贝好的临时对象返回去,然后函数结束,析构函数释放d。拷贝构造是给一个没有赋值的对象进行拷贝赋值。
2024-07-02 00:03:20
937
原创 对类与对象的(二)补充
内部有指针或者一些值指向资源的,就要写析构释放,写拷贝构造完成深拷贝的。如Stack Queue。值得注意的是 无参的构造并不是没有参数,而是不用参数传参就可以构造的函数就是无参构造。默认构造函数有三种 :全缺省的构造函数 无参的构造函数 和编译器默认生成的构造函数。除非像两个栈是实现一个队列的情况,都是自定义类型,可以不用再对队列写一个构造函数。2.一般情况的构造函数都得自己完成 因为编译器对内置类型不做处理。1.Date这样的构造函数 析构函数 拷贝构造。,一般不用写析构的,就不用写拷贝构造。
2024-06-26 16:41:42
222
原创 类与对象(1)
比如:入学时填写的学生信息表,表格就可以看成是一个。也可以声明放在.h文件里,然后在.cpp文件里写定义。public修饰的成员在类外可以直接被访问。一样的东西,限定了类有哪些成员,定义出一个类。如果后面没有访问限定符,作用域就到。注意:在继承和模板参数列表位置,修饰的成员在类外不能直接被访问。,类的所有成员都在类的作用域中。在类体外定义成员时,需要使用。一个类可以实例化出多个对象,类,来描述具体学生信息。之前在数据结构初阶中,用。可以当成结构体使用。定义类是一样的,区别是。定义的类默认访问权限是。
2024-06-26 16:29:59
262
原创 类与对象(2)
我们给s2进行拷贝构造的时候,我们其实是先给d进行一个拷贝,把s1先拷给d,因为函数栈帧上我们知道,传值调用的时候形参和实参并不是一块空间,把实参的内容拷贝到形参。如果我们用的是引用,调用拷贝函数的时候,第一次就是s1的实参,直接就可以使用,把s1的实参直接拷贝给d,d再给s2使用。.两种情况不用写:a.无资源清理的 b.内置类型成员没有资源需要清理的,剩下的都是自定义的成员,如MyQueue,就是用栈实现队列,栈里面自己写了,就可以自己调用.编译器会自动生成一个无参的默认构造函数,一旦。
2024-05-10 16:08:33
616
原创 继续学习排序
大家可以看到我们以每个的数字作为下标,然后把tmp数组中下标是arr里面数字的位置进行增加,只要遍历tmp数组然后把不为零的地方进行操作,它的下标就是这个之前数组的数,这个下标的数就是代表这个数有几次,然后遍历这个新数组,从下标零开始,那样的话不就把顺序也排好了。那么我们可以在这堆数字里找出一个最小值,每个数组的数组减去最小值,成为下标,那么空间浪费就会很少。这个排序适用于数组范围比较集中的,因为我们把数组里面的数作为新数组的下标,这样我们就可以记录这个数出现的次数,大家看代码把,应该会比较清楚。
2024-04-23 18:02:20
168
原创 学习一下选择排序,快速排序
那么right找的是什么,找的是比key小的数字,它停下的地方就是比key小的地方,所以left向右走,碰到的时候,key绝对要比相遇的大。通过动图我们可以直到快速排序的原理是,以左下角的数为key,然后右边的指针先走,right去找比key小的数,left再走,去找比key大的数,然后两个数进行交换,然后right再往左走,left再走,直到左右相遇,也就是left==right了,最后一步把key和left和right相遇的位置进行交换。并且,他们相遇的地方。为什么,相遇的地方一定比key小呢?
2024-04-17 16:45:46
417
原创 学习几道树的题
如果我们开始遍历root,当root一个结点的值和我们subRoot 这个树的根结点相同的时候,那么我们就把root的结点和subRoot的结点传递给isSameTree刚才那道题写的函数中,这样的话,那我们说一下遍历root的思路。开始遍历,也就是root到空指针的时候,subRoot也得是空,否则就肯定不是一样的树了,当然左子树和右子树都不一致才能这么说。首先我们在树的学习中,遍历树,遇到空就要结束返回,这是肯定的,我们遍历到了两棵树的结点,如果一棵树的结点已经是空了,而另一棵树不是空,那肯定不相同。
2024-04-16 18:29:31
273
原创 学习部分排序,插入排序,冒泡排序以及希尔排序
我们要把6进行前面的插入,那我们要进行比较,首先确定一个end的指针,然后他指向的数字就是我们需要比较的,如果end指向的数比我们end+1 的大的话,那我们就往前挪一个,让end指向的数位置换到刚才end+1 的位置,也就是6的位置。那么end就是在有序数组的最后一个,然后把end+1的位置存进tmp,如果比较成立,end的数字向后移动,覆盖end+1位置的数,当如果是逆序排列,end就会到达-1的位置,那么遍历也就结束了,这也成为了我们while的判断条件。间隙越大,换的越快,越不接近有序数组。
2024-04-15 17:04:05
506
2
原创 循环队列的实现
我们想想如何实现队列的功能呢,队列的原则是先进先出,那么我们就需要一个指针一直在队列的头帮助我们获取结点,出队列的时候就让front向后移动。我们只要控制好队列的长度,下标每次增加的时候%一下就会控制在0~这个范围。首先我们要画图,我们要知道队列是像单链表那样用地址链接起来的。但是我们观察这道题,队列的长度是一定的,并且要循环,那这样的话我们不如使用数组的方式来进行实现。rear是尾把我们使他每次都指向最后一个元素的下标的下一个,这样我们添加的时候直接插入该下标再++,当然你也可以选择先++再插入。
2024-04-13 10:54:59
518
1
原创 队列和栈的相互实现
我们由图可以看出,如果插入一些元素之后,我们获取栈顶元素就是最后队列的最后一个元素,那我们是不是就可以把队列一的内容一个一个移动,这样直到队列只剩下一个元素之时,我们此时获得的队列元素就是栈顶的元素,如果我们再次插入5 6,那我们是插入队列一还是队列二呢,如果我们插入队列二,如何获得栈顶元素六呢?在我们最开始往进插入的时候,随便插入,一直插入那个不为空的队列,只要保证一个空,一个不为空就可以了。我们想想该如何查此时的栈还有没元素,两个队列全是空的肯定是空,只有一个队列有元素,那栈就不为空。
2024-04-10 17:37:03
538
1
原创 继续学习堆
建立的是大堆,那我们的堆顶就是最大的元素,既然最大的我们有了,加上我们之前学过一次如何删掉堆顶元素,所以我们建设大堆,接着交换堆顶和堆尾,像删掉堆顶那样,再进行不加入刚才最大元素,重新排列,找出此时的堆的最大元素,然后再交换。假如我们使用建设小堆的原理来排序,那么堆顶一定是最小的元素,剩下的按照左子树比右子树小的原则进行排列,但不一定是我们要的升序。冒泡排序时间复杂度是O( n^2 ),n是一万还好,如果是n是一亿甚至更大呢,那时间将非常大,所以我们将用堆实现一种更快的。今天我们来学习一下对 堆的排序。
2024-03-31 14:32:54
540
1
原创 学习实现堆
如果我们把头结点和尾结点交换位置,并且减小sz,是不是就实现了减去堆顶的问题 ,那么堆的顺序坏了,我们使用向上调整方式,是不是就可以完成对堆顶的删除呢,那我们用向下调整的方法,实现一下后面的功能。尾插结束之后,我们理一下向上调整的思路,向上调整(建立小堆)那底下的一层的结点比自己的父亲结点小就要和父亲结点交换,然后child的下标变成了父亲的下标,再通过child的下标找父亲结点,再比较,直到不再进行交换或者不再父结点到了堆顶。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。
2024-03-29 17:15:22
1147
1
原创 学习一下树
我们通常用一个左孩子和右孩子的方式用来表示树,这个设计非常精妙,只把树的每层最左边的那个定义成长兄,长兄根据链表的方式把其他的“兄弟姐们”链接起来,但是用它表示二叉树不如用数组为底层结构的顺序表更方便。顺序表的结构用来表示顺序结构,数组实现的方式,就只能表示完全二叉树,如果分叉较多,用顺序表的方式非常不方便。(1)如果i=1,则结点i是二叉树的根,无双亲,如果i>1,则其双亲结点是结点[i/2]:若一个节点含有子节点,则这个节点称为其子节点的父节点;:一个节点含有的子树的根节点称为该节点的子节点;
2024-03-27 17:35:44
1477
原创 练习一道经典链表题目
我们可以看到假设是报号为三的人走,那我们只要定义一个count 当他增长到三的时候,让此时循环到的人走,那我们是不是的需要一个指针进行循环呢,那我们还需要一个指针进行记录辅助这个遍历指针,否则,将这个指针指向的空间进行释放,那么就找不到链表了,所以我们移动一个位置,count就加一次,然后一前一后两个指针进行挪动。接着我们是实现遍历次数符合则释放空间,剩下最后一个数据时候,在循环单链表中的特点是什么,那就它的尾结点的next指针指向的是自己的头结点。所以这个就是我们的循环遍历的终止条件。
2024-03-26 17:38:26
142
原创 学习一下栈吧
有了顺序表的基础,大家可以认为这里很简单,有所不同的是我们这次取的是栈顶的元素,栈顶的元素就是我们后插入的元素,那我们直接在顺序表里进行尾插,然后尾巴就是栈顶元素。我们如果插入一个元素,top就会向后移动一个位置,那么top的位置就是栈顶元素的下一个,所以我们需要减一才能获取到栈顶元素。因为是特殊的线性表,我们通过对顺序表,单链表,双链表的学习,我们大概也了解了,所以我们话不多说,直接开始思路。我们实现顺序表的时候,会有头插尾插,我们栈只要求我们要后进先出,那我们直接尾插,获得尾巴就好了,不用在考虑了。
2024-03-21 12:40:21
256
1
原创 时间复杂度和空间复杂度
我们用刚才的这个图来确定,离散数学中学的二叉树,我们就按照前序遍历,走到尽头,最多就是开辟了n个额外空间,能重复使用,所以,别的枝杈再用的时候,也是之前的空间,因为函数递归,遍历结束后就会往返这个,空间就会被回收利用。我们值得一提的是一个叫做卡瑞尔公式的,这个公式让我们计算时间复杂度的时候要通过最坏的结果进行计算,举个例子,就是二分查找,如果再坏的话,就是在最后两个数之间找到,这样来计算它的时间复杂度。这个函数递归就区别刚才的时间复杂度,空间一直递归下去,一直需要创建,所以是O(n);
2024-03-19 00:25:17
420
1
原创 学习双链表
尾插的话,我们如何找到末尾的那个结点呢,头结点的prev是不是就存储的末尾结点,并且,我们还要让新插的数据的prev链接上末尾结点,那我们应该先让新插的数据的prev和next指针先存刚才的链表的尾结点,存储完了,在改头哨兵位的prev的结点,让新插的数据成为新的尾结点。”,有了头结点就可以双向循环了。5.头插,我们有了哨兵位,哨兵位不动,哨兵位的next结点,就是我们要头插的位置,这么来看,我们可以受尾插的启蒙,先让新插的数据存储原来链表的各个地址,再让链表存储它的地址。2 先来初始化一下我们的哨兵位。
2024-03-18 11:58:27
339
1
原创 接着介绍单链表的题目
所以我们试试三个指针,第一个在最前面,负责遍历,第二个紧跟着它,第三个紧跟着第二个,当第二个把next指针指向第三个的时候,再把第三个存第二个的地址,然后第一个和第三个就再往前走。这样看的话,不能完全和数组一样,数组可以先合并再排序,但是单链表排序会非常繁琐,我们不让边排序边合并,所以呢,我们建一个新链表,两个指针进行遍历,小的先放,谁先放进了新链表,谁的指针就往前放一个,但是我们要防止空指针的出现,假如两个链表都是一个,那么进行挪动之后,我们要防止出现空指针->val 的情况。
2024-03-18 01:25:06
206
1
原创 学习一下单链表
因为单向循环,所以我们遍历一下,尾巴的标志是什么,就是它的next指针指向的是NULL,所以我们要以它作为条件,进行循环遍历,但是我们还需要尾巴的上一个结点,因为它成了新的尾结点,所以我们有两种思路,第一种就是定义两个指针,两者一前一后,紧挨着进行遍历,最后释放尾结点即可,第二种思路,就是用指针的next->next进行判断为空,值得注意的就是,如果只有一个数据,此时就是尾结点,-next=NULL,不能将NULL再指向next,会报错,所以我们先写一个只有一个数据的时候。中的指针链接次序实现的。
2024-03-17 01:50:59
1301
1
原创 接着介绍一些链表练习的题目
因为单链表的原因,我们如果想要更改是val的节点上一个节点的next指针,我们需要两个指针,一个在前,一个在后,一个负责遍历,一个负责更改。<2>第二种思路,我们可以遍历链表,让链表中指向val的值不是val的链表存进新的链表,然后我们结束时要返回新的链表的头节点,所以呢,我们要有一个头节点用来返回,但是怎么做才能继续往后延长新链表呢,所以我们还要一个指针一直在尾部,负责链接下一个传来的值。紧接着我们发的顺序表的题,我们接着来练习一些单链表的题目,晚上ss会更新单链表的写法。
2024-03-16 18:42:47
201
1
原创 关于顺序表的练习
所以我们只需要定义两个指针,一个指针负责遍历,一个负责接受不是val的值,第二个指针和第一个指针遇到不是val的值就越过,遇到是的第一个指针接着向前遍历,第二个停下,停在是val的地方,第一个接着遍历,直到遇到不是val的值,第二个指针把它存进去,再往前走,思路清晰,代码实操。把数组2合并到数组1上,首先要求就是数组1的空间足够,接着还要求我们要形成非递减顺序的数组,我们两个思路,可以边排序,边插入,也可以先把两个数组头尾想接再进行冒泡排序,第二种比较实现,我们尝试第一个。那我们试试从后面开始。
2024-03-16 11:56:57
276
2
原创 分享一下求十进制数再二进制情况下,数字1的个数
第三种:我们可以知道,减一就会把二进制的第一位改变成相反的(0->1或者1->0),然年后其他位置的一就会移动位置,但是数字1的个数并没有变化,ss就不实际操作了,大家可以举个数字试试,每次&就会减掉一个1,所以我们只要每次把最后一位减一,两个值进行&,得到的结果就可以计算了,我们可以知道 二进制的第一位,是2的零次方乘以这个位上的数,其他的位置都是二的各种次方,所以其他位都是二的倍数,如果第一位为一的话,那么这个数%2一定有1,所以我们只要%2一次,右移一位即可,直到这个数为零,思路清晰,代码实操。
2024-03-16 00:58:07
293
1
原创 介绍字符串的库函数(2)-模拟实现strcmp,strstr
我么首先要遍历两个字符串,也就是我们要一个字符一个字符的比较大小,在遇到'\0' 之前如果有不同的字符,则根据情况返回正整数或者负整数,如果遍历完了字符串,发现两个字符串一模一样,我们就要返回0;如果像ss举例,大家就会发想如果像往常那样遍历,就不好判断出来,那么我们再定义三个指针,一个arr1,一个arr2,最后一个负责切换遍历arr1的起始位置。其实可以发现,如果这两个字符串中没有重复的字符连在一起,我们只需要遍历字符串1就可以了,找到第一个字符相同的,看看后面相同不相同。我们可以看到很简单就实现了。
2024-03-15 14:06:05
311
1
原创 学习一下顺序表吧
把该位置的数据之后的数据往后挪一位,把该数据插入进去,是不是也很简单呢,简直和头插一样,只不过一个头不固定,一个头固定。.第三种就是我们要用的一种扩容原则,成倍扩容,我们以二倍为例,也就是2,4,8,16,32。.第二种扩容方式是固定一个值的扩容,假如每次扩容一百,那么我存了101,那是不是就浪费了99的空间,这样做是有一点浪费的。第二个就是运用assert的断言,我们目的就是为了防止空间的乱用,避免传过来的是空指针从而导致数据的存储失败。5,写完了尾插,我们写一下头插。也就是扩容,怎么扩。
2024-03-15 00:52:28
444
1
原创 介绍一个字符串的运用的部分库函数(1)
这个库函数,在我们初期时候就见到过了,它求得是'\0' 之前的字符个数,如果你建立的字符串没有'\0' ,它就会一直增加字符个数,直到内存中遇到了'\0',求出来的数据是随机的。在图片中我们看到,它的返回类型,以及调用函数,需要传参的东西,此函数可以将source的字符串拷贝到 destination,让我们看一下代码实操。看一下它的用途,比较两个字符串,它会从字符串一个字符对一个字符的比较,每个字符都有对应的ASCLL码值,就可以比较出它的大小。<2>.目标的空间必须足够大,可以拷贝源函数。
2024-03-14 15:32:33
167
原创 介绍一下指针数组和数组指针
这样看的话,只与我们前面的代码只差一个括号,括号的优先级要比[ ]高,所以再(*p)中,p先和*结合,这样的话,p首先是一个指针变量,这个指针指向的是一个存储了十个整型的数组,让我们举个例子看一下吧。为什么解引用两次呢,第一次解引用是是相当于通过解引用&arr,找到了这个数组,结果数组的地址加i的情况,再次解引用,就完成了找到数组成员的目的,但是我们一般以二维数组更好的展示数组指针的应用。像我这样的初学者,大家一定要注意接受二维数组传参时是用数组指针接收。举个例子来运用一下指针数组。初来乍到,请大佬关照。
2024-03-13 23:58:00
152
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人