- 博客(60)
- 收藏
- 关注
原创 string类模拟实现
而且我们会发现,我们注释掉的无参数和全缺省参数是不一样的,一个_str=nullptr,一个则是"“,这又是为什么呢?nullptr不仅会让strlen无用,在后续返回c_str的时候也会出现问题(因为c_str返回的就是_str,是指向字符串的指针,而nullptr是无法使用的),而且我们这里为什么给的是个空串,而不是”\0"呢,这是因为const char* str常量字符串本来就是有"\0"在最后面的,如果我们给的不是空串,就重复填入了一个\0,这样的话是无意义的,所以给一个空串是刚刚好的。
2024-07-12 14:42:55
924
原创 string类(STL开始)
相信大家都知道STL在C++中的重要性,作为其模板库中的一部分,包含了常见的数据结构和算法,是C++的标准库而我们今天要讲的String类(String底层是一个字符顺序数组的顺序表对象,可以归类为容器),其实其诞生于STL之前,并不属于STL,但是你却可以从中看到属于STL的一角,相信学了String类之后,在后面学习STL时,vector等类对大家来说一定手到擒来。
2024-07-08 17:37:12
816
原创 C++内存管理
这是我们用两种方式创建一个A类对象的过程,我们会发现,在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会。并且new在失败之后还会抛出异常,不需要我们手动检查,但这里我们还没有学到抛异常这个部分,所以我们之后再说我们会发现,其实new和delete都是为了自定义类型而创建的,如果用C语言的内存管理会很麻烦new的原理调用operator new函数申请空间在申请的空间上执行构造函数,完成对象的构造delete的原理。
2024-05-14 20:04:41
1071
原创 类与对象(三)(日期类实现)
既然我们无法在类中定义,那么我们就可以尝试在全局中使用,但是这也有一个问题,那就是我们需要封装,所以如果定义全局函数,那么如何去调用日期类里面的成员变量呢?这里我们就需要用到friend:友元声明,可以访问我们的私有对象,需要在头文件的类里面声明,然后在全局定义,这样子才得以将我们的对象顺序调换;首先,我们假设,this指向的对象为大一些的数,而另一个指向的则是小一些的,定义一个flag为1,用来确定正负;这个也很好解释,如果我们先实现+=这些,那么我们的+=不会创建一个临时对象,而+会;
2024-04-25 17:59:50
736
原创 类与对象(二)
原因:赋值运算符如果不显式实现,编译器会生成一个默认的。此时用户再在类外自己实现一个全局的赋值运算符重载,就和编译器在类中生成的默认赋值运算符重载冲突了,故赋值运算符重载只能是类的成员函数。
2024-04-25 17:46:33
731
原创 类和对象(一)
/ 类体:由成员函数和成员变量组成// 一定要注意后面的分号class为定义类的关键字ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略。类体中内容称为类的成员:类中的变量称为类的属性或成员变量;类中的函数称为类的方法或者成员函数声明和定义全部放在类体中(就像刚才的结构体示例一样),需注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。
2024-04-10 21:36:38
691
1
原创 C++入门(二)
我们总结一下:引用:1、做参数(a、输出型参数 b、对象比较大,减少拷贝,提高效率(指针也可以做到这些,但是引用更方便)减少拷贝的原因在于,引用和原本的变量用的是同一空间,不会开辟新的空间,所以节省了内存的消耗2、做返回值(a、修改返回对象 b、减少拷贝提高效率)在早期C/C++中auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量,但遗憾的是一直没有人去使用它,大家可思考下为什么?
2024-04-09 21:53:18
654
原创 寒假作业Day 13
答案选C,3个,很简单a,b入栈,b出栈;c,d入栈,再出栈;e,f同理;a再出栈,g入栈再出栈所以进栈最多的时候是3个元素已知一个栈的入栈序列是连续的整数1到n,且已知第二个出栈的元素是3。这意味着在3出栈之前,2必须已经入栈但还未出栈。因此,在3出栈后,紧接着1和2也必须依次出栈,以满足题目条件。在此之后,栈为空,剩下的元素4到n可以按任意顺序入栈和出栈。所以,第三个出栈的元素p 3 可以是4到n中的任意一个,共有n−3种可能。
2024-03-18 19:32:40
794
原创 寒假作业Day 12
队列是先进先出的线性表,既能插入数据,也能删除数据A:ABCD,一进栈就出栈;B:DCBA,全部进栈之后再出栈C:ACBD,先进A,然后出,进BC,然后出,最后进D然后再出D:DCAB,CD限制了AB的顺序,所以出栈只有可能是BA,故D错误有四个不同的组成:ABC,CBA,ACB,BAC分别由这几个字符串组成:①“A”,“B”,“C”②“CBA”③“A”,“CB”④”BA“,“C”重复的是A和C,所以至多可以组成6个不同的字符串。
2024-03-14 20:08:23
723
原创 寒假作业Day 11
在链式存储结构中,栈的大小是动态的,只受限于系统分配给程序的内存大小。因此,理论上,链式栈不会因为空间不足而“满”。所以,不需要判断栈满。:链式栈通常有一个指针指向栈顶元素。如果这个指针是NULL或者指向某个表示空栈的特殊节点,那么我们可以判断栈是空的。因此,需要判断栈空。这里画图操作,p->q->…这样的一个样式,让p的后继指针指向原本q指向的地方,再把q free掉其实就可以了A:随机存取是顺序表的优点,B很明显也是错误的,结构体里面不仅有元素值,还有指针,不可能花费的存储空间更少;
2024-03-14 19:11:02
433
原创 寒假作业Day 10
1、下列数据结构中,不属于线性表的是( )A.队列 B.顺序表 C.二叉树 D.链表A. 队列:队列是一种特殊的线性表,它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。因此,队列是线性表。B. 顺序表:顺序表是用一段地址连续的存储单元依次存储线性表的数据元素。它也是线性表的一种实现方式。C. 二叉树:二叉树是每个节点最多有两个子节点的树结构,通常子节点被称作“左孩子”和“右孩子”。二叉树并不是线性表,因为它的元素不是按照线性顺序排列的。
2024-03-10 17:44:21
448
原创 寒假作业Day 09
因为一开始的for循环,k<2NN,所以复杂度为2N方,而后面的M=10的while循环,则是10,复杂度为常数级,所以2N方+10,近似于N方,即O(N^2)这是一个计算阶乘的递归函数,当n=0或者1的时候,无需递归,直接返回;而n=2开始,就需要递归n-1次,因此,递归调用的深度是n;又因为深度是n,而调用的时间复杂度为O(1),所以整个函数的时间复杂度为O(n)这个函数中传递了一个n进去,初始化i=1,当i<=n时,i就一直乘以2,直到i>n时退出循环;
2024-03-10 15:33:18
366
原创 寒假作业Day 08
1、下列关于 const 和 #define 定义常量的区别,说法不正确的有( )A: define宏是在预处理阶段展开。const常量是编译运行阶段使用B: 宏没有类型,不做任何类型检查,仅仅是展开。const常量有具体的类型,在编译阶段会执行类型检查C: define宏仅仅是展开,有多少地方使用,就展开多少次,不会分配内存。const常量会在内存中分配(可以是堆中也可以是栈中)D: const定义和#define定义的常量在程序运行过程中只有一份拷贝。
2024-03-09 16:45:22
1101
原创 寒假作业Day 07
函数rewind的作用是使文件位置指针重新返回文件的开始位置。这是C语言程序中的库函数,它针对的是文件内部的位置指针,而不是文件指针。文件内部的位置指针会随着对文件的读写操作而向后移动,而文件指针则是指向整个文件,如果不重新赋值,文件指针不会改变。通过调用rewind函数,可以方便地将文件位置指针重置为文件的开头,从而可以重新读取文件的内容。所以正确选项为A对于Windows系统,文件路径使用反斜杠()作为分隔符。
2024-03-07 18:38:27
709
原创 寒假作业Day 06
A正确,比如创建一个四个int类型的数组就可以这样创建:int* a=(int*)malloc(sizeof(int)*4);B和C:这都是在描述realloc的过程,这是realloc的两种情况;D:错误,只是会删除标记,但并不会清除空间内容2、如下程序输出的结果是什么( )我们可以明显看出,List_t是一个双向链表,其拥有一个next指针(后继指针),和一个prev指针(前驱指针),以及一个十分特殊的结构:“柔性数组成员”或“零长度数组”data[0]。它允许你在结构体的末尾有一个大小可变的数组。
2024-03-04 20:40:29
541
原创 寒假作业Day 05
首先创建了一个二维字符数组,两行四列,并且第一行复制一个you过去,第二行复制me过去,第一行的最后一个字符复制&,所以打印arr的结果是you&me2、如下C程序,在64位处理器上运行后 sz 的值是什么( )这个跟结构体的内存对齐有关,首先我们看处理器是64位的,也就证明指针的大小是8个字节,而默认对齐数是8,故对齐数还是8,而int则是4,char则是1,而结构体总大小需要为最大对齐数的整数倍,即8,16,24等等。
2024-03-04 20:40:09
724
原创 寒假作业Day 04
首先我们分析一下,char *str[3]是字符指针数组,其三个字符指针分别指向"stra",“strb”,“strc”,而char *p则是字符指针,被赋值stra字符串的首地址,所以一开始输出的是stra,而p++之后则是跳过一个字符的位置,输出tra,最后输出ra故输出结果为stra tra ra2、下列代码输出的结果是什么( )首先创建了一个整形数组m,存储了10个元素;定义了一个名为p的指针,该指针指向一个包含4个整数的数组。
2024-03-03 15:53:29
1070
原创 寒假作业Day 03
在C语言中,字符型指针char *p;通常用于指向字符数组(即字符串)的首字符。对于给定的选项,我们来分析每一个选项是否可以将字符串正确地赋值给p:getchar()函数从标准输入读取一个字符,并返回该字符的ASCII值。由于getchar()返回的是一个int类型的值(它可能是EOF,即文件结束标记,这是一个负值),所以直接将这个返回值赋给char *类型的p是不正确的。此外,即使忽略类型不匹配的问题,getchar()也仅仅读取一个字符,而不是整个字符串。
2024-03-03 11:24:07
932
原创 寒假作业Day 02
首先char* s[6]是指针数组,也就是其存储的都是这些字符串的地址,其实际上的类型为char**,而fun函数传入了s数组的首地址。这与 f 所期望的 int** 类型匹配,因为 q 的类型实际上是 int* [3],它会被转换为指向其第一个元素的指针,即 int**。void (*s[5])(int) 是C语言中的一个声明,它定义了一个名为 s 的数组,该数组包含5个元素,每个元素都是一个指向函数的指针。&a 是数组 a 的地址,其类型是 int (*)[4],即指向包含 4 个整数的数组的指针。
2024-03-01 22:03:32
701
原创 寒假作业Day 01
这里我们可能会以为sizeof(para)等于100,因为char类型占一个字节的内存空间,而里面有100个元素,所以我们理所当然认为其答案为100,但是在函数的参数中,其被自动转换成了指向字符的指针,实际上只传递了数组的第一个元素的地址,而指针的大小不论类型都是4个字节的大小,所以第一个答案为4;这里依旧是指针的问题,首先,我们传入的是数组s的首地址,p=p+1,即往后走了一个元素大小的地址,也就是从一开始的‘1’的前面,走到了‘2’的前面,所以这个时候的*s也就等于第二个元素2,输出的结果为2.
2024-02-28 21:09:05
806
原创 归并排序+非比较排序
经过之前的选拔,你已经成功通过了排序闯关,接下来看看总结,看看你有没有忘记什么(doge)①直接插入排序:直接插入排序是一个一个从后面插入,并与前面的值比较,逆序的时候(最差情况),要排升序就需要从头到尾都要移动,逐次移动1+2+3+…n-1次,是一个标准的等差数列,所以时间复杂度O(n^2);没开额外空间,所以空间复杂度O(1);说到稳定性,在这里先要提醒一下大家,这可指的不是性能的波动,而是数组里面有相同的值,保证其相对顺序不变就是稳定的。
2024-02-01 12:26:19
1050
原创 交换排序(快排)
(比如这里就是右边先移)在移动过程中,如果左边的数字比坑位上的数字大,或者右边的数字比坑位上的数字小,就继续移动。一旦左边的数字小于等于坑位上的数字,或者右边的数字大于等于坑位上的数字,就将当前位置与坑位交换。快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。
2024-01-30 13:58:40
1107
原创 选择排序(堆排序和topK问题)
eg.n=2^h-1上面的T(n)都是T(h),到下面才是T(n),写错了QAQ由此可以看出,向下调整建堆的时间复杂度为O(n),下面我们计算向上调整建堆的时间复杂度由此可知:向上调整建堆的时间复杂度为O(nlogn),是大于向下调整建堆的,这样子的话,我们以后如果使用堆排序,我们就可以直接忽略向上调整算法,只写向下调整算法,代码量可以更少,时间复杂度也更精简。
2024-01-25 15:25:59
1109
原创 排序(插入排序)
它的基本思想是:先将整个待排序的记录序列分割成为若干子序列(由相隔某个“增量”的记录组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;此时end+1=0,也就是数组的第一个元素,最小的元素,刚好就是1。
2024-01-23 16:09:22
1025
原创 二叉树简单OJ题(及其后续函数补充)
首先呢,我们还是把问题分化一下,求一棵二叉树是否为单值二叉树,还是可以分为几个部分:根节点 左子树 右子树而我们向下遍历的时候,其实就是在这个节点以及其左子树和右子树中找,是否值都相同,这样一来,代码写出就十分明了了。
2024-01-21 17:21:54
930
原创 二叉树(三种遍历方法等)
在学习二叉树的基本操作前,需先要创建一棵二叉树,然后才能学习其相关的基本操作。由于现在大家对二叉树结构掌握还不够深入,为了降低大家学习成本,此处手动快速创建一棵简单的二叉树,快速进入二叉树操作学习,等二叉树结构了解的差不多时,我们反过头再来研究二叉树真正的创建方式。
2024-01-19 18:52:47
999
原创 二叉树(堆)
树是一种的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说有一个特殊的结点,称为,除根节点外,其余结点被分成M(M>0)个互不相交的集合T1、T2、……、Tm,其中每一个集合Ti(1<= i <= m)又是一棵结构与树类似的子树。因此,树是递归定义的。
2024-01-16 19:13:09
829
1
原创 栈与队列※
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。出栈:栈的删除操作叫做出栈。出数据也在栈顶。
2024-01-13 13:12:09
335
原创 数据结构之双链表
但是传二级指针,又会影响接口的一致性,而我们的用户并不知道一级指针和二级指针的区别,这样子,使用起来就会很麻烦,所以,我们选择的方法是,在销毁之后,手动给plist置为空,而不使用二级指针,保证接口的一致性。我们会发现phead显然已经为空,而plist的后面的数据也已经清空,但是plist这个头节点却并没有置为空,但我们在销毁函数中明明已经写过了,这实在令人疑惑。如果要修改原本的头节点指针,需要传入一个指向头节点指针的指针(即二级指针),并在函数内部通过间接访问来修改原本的指针。相比之下,单链表只有。
2023-10-28 19:58:56
63
原创 数据结构之单链表
图中指针变量 plist保存的是第⼀个节点的地址,我们称plist此时“指向”第⼀个节点,如果我们希望plist“指向”第⼆个节点时,只需要修改plist保存的内容为0x0012FFA0。⻋厢是独⽴存在的,且每节⻋厢都有⻋⻔。想象⼀下这样的场景,假设每节⻋厢的⻋⻔都是锁上的状态,需要不同的钥匙才能解锁,每次只能携带⼀把钥匙的情况下如何从⻋头⾛到⻋尾?当我们想要保存⼀个整型数据时,实际是向操作系统申请了⼀块内存,这个内存不仅要保存整型数据,也需要保存下⼀个节点的地址(当下⼀个节点为空时保存的地址为空)。
2023-10-25 16:25:26
75
原创 数据结构之顺序表
比如数组无法自由改变空间大小,一旦创建就无法更改,而实际的应用中,数据的大小都是在实时发生变化的;数组我们应该都很熟悉,在C语言的学习当中,我们经常使用数组来存储同类型的数据,比如我们想存储1~100的数据,就会创建一个可以容纳100个int类型大小的一维数组。删除元素比起添加元素少了一个问题,那就是空间大小是否足够,但另一个问题就是需要注意空间里是否还有足够的元素删除,这是删除元素的问题。尾删很简单,只需要让有效数据的个数-1,就可以达到删除数据的效果,而头删则需要移动数据的位置达到效果。
2023-10-12 14:57:33
76
1
原创 结构体介绍
我们都知道,数据有很多种类型:整型,字符型和浮点型等等,但有时候,这些类型并不够用,所以这个时候,就需要用到自定义类型。而今天我们要讲的就是其中之一的结构体首先我们先给大家写一段代码,举一个例子:上面的Stu就是结构体的类型,而大括号里变量的称作结构体成员,是结构体的重要组成部分再给大家看一段代码大家应该可以看到分号前面跟着的Un,其实就是结构体Stu的变量,我们可以在结构体的最后创建变量,不一定需要在main函数中再创建而如果我们去掉Stu的话,又会发生什么呢?这样子做的话,这就是一个匿名
2023-09-23 16:56:40
116
1
原创 整型与浮点数在内存中的存储(下)
这意味着,如果E为8位,它的取值范围为0 ~ 255;但是,我们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,存⼊内存时E的真实值必须再加上⼀个中间数,对于8位的E,这个中间数是127;①IEEE 754规定,在计算机内部保存M时,默认这个数的第⼀位总是1,因此可以被舍去,只保存后⾯的xxxxxx部分。举个例子,char a=5.5,那么十进制的5.5,写成二进制就是101.1,因为0.1就是2^(-1),而这也就相当于1.011*2 ^ 2,这样S=0,M=1.011,E=2。
2023-09-18 17:06:45
53
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人