- 博客(52)
- 收藏
- 关注
原创 数据结构——二叉树链式结构的实现(下)
一般大家求高度的时候,都会这样去写代码,但这样写是有问题的,使用三目运算符使虽然让代码行数减少了,但造成了空间栈的浪费,因为在算左子树深度和右子树深度时,求出来的结果值只用在了判断它们俩谁大谁小的问题上面并没有保存返回值,当判断完左还是右大以后,后面运行的代码它还要再次去计算左子树或者右子树深度再+1,造成了重复计算(栈浪费),如果是数据量大会造成栈溢出。解决办法就是创建变量接收左子树或者右子树的深度,再进行比较,这样就不会造成栈溢出的问题,也节省了空间和提高了效率。那么使用层序遍历是最好的。
2024-05-05 17:40:53
704
原创 数据结构——二叉树链式结构的实现(上)
学习二叉树结构,最简单的方式就是遍历。所谓二叉树遍历(Traversal)是按照某种特定的规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次。访问结点所做的操作依赖于具体的应用问题。遍历是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。
2024-05-02 16:52:59
614
原创 数据结构——二叉树(堆)
普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费,因此完全二叉树更适合使用顺序结构来存储。二叉树一般有两种结构存储: 顺序结构和链式结构。顺序结构也就是顺序表(数组)来存储,一般只有完全二叉树和满二叉树适合数组来存储。其他二叉树会有空值——会造成空间浪费。而我们通常把堆(一种二叉树)使用顺序结构的数组来存储。二叉树顺序存储在物理上是一个数组,在逻辑上(想象中的)是一颗二叉树。小堆:每个父亲都小于等于孩子 parent=childl
2024-05-01 16:27:16
1212
4
原创 C++——继承
继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复用,继承是类设计层次的复用。
2024-04-08 12:21:10
783
原创 不再恐惧指针,指针详解
int*pa=&a 的意思是 *p表明是一个指针变量 p指向的对象类型是intp解引用访问的对象大小字节是int(4个字节)
2024-01-10 23:24:56
884
原创 C语言——指针题目“指针探测器“
如果你觉得你指针学的自我感觉良好,甚至已经到达了炉火纯青的地步,不妨来试试这道题目?程序的运行结果是什么?运用自己的指针理解,不妨尝试下。
2023-12-28 19:15:48
540
原创 “C语言“——scanf()、getchar() 、putchar()、之间的关系
如果scanf输入过程中遇到空格 回车键等字符,scanf自己处理不了的读取字符时,就用getchar来解决,如果有多个处理不了的特殊字符就用while循环来处理(scanf处理不了的空格 回车键等特殊字符),配合getchar和putchar来给scanf的正常使用(擦屁股)。
2023-12-24 19:41:25
557
原创 C语言——预处理详解(#define用法+注意事项)
一般我们是不建议在语句最后加上分号的,因为这样会容易导致出现问题比如不能在宏替换后面加分号,因为在预处理阶替换时会出现语法错误 y=100;;两个分号会变成两个条语句 else不知道与谁匹配#define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro) 或定义宏 (define macro)。比如许多C 的编译器提供了一种能力,允许在命令行中定义符号。用于启动编译过程例如:当我们根据同一个源文件要编译出不同的一个程序的不同版本的时候,这个特性有点用处。
2023-12-12 00:42:58
857
原创 Linux——vim编辑文件时——.swp文件解决方案
当我们vim test.cpp进入编辑文件。却忘记了保存退出 再次进入就会出现一下画面当你摁下Enter键位 出现以下几个选项O——是只读不写E——是正常打开文件但不会载入磁盘内容R——是加载存储磁盘的文件(但我们忘记保存时,系统会自动帮我们保存我们刚才编辑文件内容——在一个.swp文件) 但我们如果不删除那个系统帮我们临时保存的.swp文件 你编辑完文件保存 再次进入时 还是会出现以上问题 并且内容只是你修改之前的原来编辑内容。Q——是退出这个编辑 回到原始输入命令行。
2023-11-28 17:32:41
1533
原创 C++——类和对象(中)完结
也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。函数名字为:关键字。注意:不能通过连接其他符号来创建新的操作符:比如operator@重载操作符必须有一个类类型参数用于内置类型的运算符,其含义不能改变,例如:内置的整型,不 能改变其含义作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this: .注意以上5个运算符不能重载。这个经常在笔试选择题中出现。
2023-11-03 00:02:14
451
原创 C++——类和对象(中)(2)尚未完结
日期类不用写拷贝构造 使用编译器默认生成的就可以完成值拷贝——可以完成我们的需要拷贝构造对内置类型完成默认的拷贝构造——浅拷贝Date 和 MyQueue 默认生成拷贝就可以用1、内置类型成员完成值拷贝2、自定义类型成员调用这个成员的拷贝构造stack需要自己写拷贝构造,完成深拷贝。顺序表、链表、二又树等等的类,都需要深拷贝。注意: 类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请时,则拷贝构造函数是一定要写的,否则就是浅拷贝。
2023-10-28 19:20:35
171
原创 C++——类和对象(中)(1)
1.一般情况下,我们都要自己去写构造函数。2.成员都是自定义类型or声明时给了缺省值 可以考虑让编译器自己生成一个构造函数。3.自己写构造函数时推荐使用带参构造(缺省值)。
2023-10-28 18:01:33
276
原创 C++——类和对象(上)
在C++中,struct类更喜欢用class代替。类体:由成员函数和成员变量组成一定要注意后面的分号class为定义类的关键字,ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略。类体中内容称为类的成员: 类中的变量称为类的属性或成员变量;类中的函数称为类的方法或者成员函数。int _top;st.Init();st.Push(1);
2023-10-28 16:25:01
152
原创 初始C++入门(2)
以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调用建立栈帧的开销,内联函数提升程序运行的效率。
2023-10-21 17:13:39
180
原创 初识C++入门(1)
后台开发,主要做一些基础组件,中间件、 缓存、分布式存储等。,目前重点掌握这两个即可,其他的版本语法可以等待工作以后随着对C++理解不断加深,再去了解其他版本语法特性。C++的介绍就到这里吧!后台开发:主要侧重于业务逻辑的处理,即对于前端请求后端给出对应的响应,现在主流采 用java。除了上述领域外,在:科学计算、浏览器、流媒体开发、网络软件等都是C++比较适合的场景,作为一名老牌语言的常青树,C++一直霸占编程语言前5名,肯定有其存在的价值。咱们不急,先听我娓娓道来,我会在下面解释到的,解开困惑的。
2023-10-16 15:34:08
177
1
原创 函数栈帧的创建与销毁(保姆级讲解)
知道和函数栈帧的创建和销毁就都会了,其实就是修炼了自己的内功,也能搞懂后期更多的知识。进入正题今天讲解使用的环境是VS2019同时在不同的编译器下,函数调用过程中栈帧的创建是略有差异的,具体细节取决于编译器的实现。首先我们要了解什么是?函数栈帧就是在函数调用过程中,程序为函数所开辟的栈空间,函数一般放在栈区。。而什么又是栈呢?栈的概念及结构栈:一种特殊的线性表,其只允许在固定的一端进行 插入和删除 元素操作。进行数据插入和删除 操作的一端称为 栈顶 ,另一端称为 栈底。
2023-10-14 16:15:51
180
1
原创 栈的概念和结构以及实现
如果我们在初始化的时候top的初始值是0,top就指向4后面,如果top想指向4本身就要初始值赋值给-1。也有可能是4 3 2 1;3 2 4 1..... 但 3 1 2 4是绝对不可能的。所以想top指向栈顶数据就初始化为-1,top想指向栈顶数据的下一个位置初始化为0。按惯例一般出栈顺序是4 3 2 1,但一定是4 3 2 1吗?如果使用单链表来模拟实现数组栈,用头做栈顶,尾做栈底。数组栈:完美符合栈固定一端的插入和删除的操作;,相对而言数组的结构实现更优一些。栈的实现一般可以使用。
2023-06-20 20:35:28
272
原创 当我与单链表分手后,在酒吧邂逅了双向循环链表.....
当链表为空,这段代码也一样适用,因为双向链表的核心就是头指针的pre和next都是指向自己,这是带头双向循环链表的优势。,这个应该没啥好说的,各位兄弟姐妹也会自己写。这个开辟结点应该没有什么好说的,带头双向循环链表多了个指针pre。,即是头也是尾,双向链表改变的是结构体,用结构体指针就够了,,用两个临时变量存储,常规连接两个变量即可。,再释放掉尾tail,最后常规连接即可。,再用一个临时变量存储,再常规连接即可。链表的种类有8种,但我们最常用的为。的时候,双向链表的指向如下图。,不像带头双向循环链表带有。
2023-05-16 19:00:09
571
3
原创 顺序表的基本操作(初始化,增,删,查,改等等)
千万不要写成ps->a[ps->sz-1]=0;但这个代码存在一定的问题,因为一直尾删ps->sz--如果一直--下去,它会出现越界,会出现ps->sz=-1的位置存放有效数据,相当于越界,当一直尾删到ps->sz==0的位置再减减ps->sz==-1,然后再进行尾插的时候就会出现越界,还有断言pos,因为在我们插入数据的时候,可能会超过size本身的容量就插入,比如有4个空间,别人在空间以外20的位置插入了30,就会发生越界行为,所以我们要断言一下0
2023-05-07 17:21:37
995
2
原创 单链表——单链表的定义及基本操作(初始化、头插法尾插法建表、查找、插入、删除、判空等)
所以我们把int重定义成 SedListdatatype,如果我们要改其他数据类型,只需要在上面改一下即可。因为结构体里面的next本身就是一个一级指针,尾插和头插,都会改变结构体里面存储的数据,由于顺序表存在以下缺陷,所以衍生出了链表,而链表种类有很多种,今天我们讲的是。我们再把结构体的名字也重定义方便实现单链表的功能实现。我们要在单链表中实现尾插和头插等等功能,这个结点包括。,因为我们有时候会需要找到头的地址,虽然有这么多的链表的结构,但是我们。,我们另写一个函数用来专门。当我们遍历单链表的时候,
2023-05-05 16:07:17
1771
原创 算法的时间复杂度和空间复杂度(2)
空间复杂度是O(N),因为在斐波那契数列在函数递归的时候 ,会有很多重复项,而函数栈帧在建立的时候,它会先选定一个空间,而空间是可以重复利用的,不累计计算,在一块栈帧用完后会销毁,在按照语句去选定下一个空间。因为递归先递推后回归,看起来规律像等比数列,也可以用错位相减法,因为斐波那契数列到第二项就不会再计算了,因为前面两项都是1,灰色部分可以忽略不计,影响不大。在main()调用完FUB1()空间会销毁,销毁不是真的销毁了这块空间,而是相当于人搬走了,地方还在,FUB2()还会在刚才的空间继续创建栈帧。
2023-04-20 18:56:13
1021
原创 算法的时间复杂度和空间复杂度(1)
你心里很开心,去消费了一万,暗自窃喜,这对于你很贵,但对于有钱人这种小钱微乎其微,有钱人也知道我们普通人的消费水平,所以cpu相当于千万富翁,我们眼中的大数字钱,不过是人家的零花钱罢了,所以,因为不确定M和N的对应的值,所以不能够确定M和N对各自的效果是不是微乎其微,书面来说是同阶的数,所以不能忽略N或M,应该是N+M。因为有N个元素,第一次比较N-1,第二次N-2,第三次N-3.....3 2 1....相当于等差数列,N*(N*-1)/2。有N个元素,每次折半查找N/2/2/2,假设找了X次。
2023-04-18 18:10:00
317
原创 C语言——文件操作(2)
从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。牢记:在文件读取过程中,不能用feof函数的返回值直接用来判断文件的是否结束。数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件。而是应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束。2. 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。
2023-04-08 21:48:08
455
1
原创 C语言——文件操作(1)
我们前面学习结构体时,写了通讯录的程序,当通讯录运行起来的时候,可以给通讯录中增加、删除数据,此时数据是存放在内存中,当程序退出的时候,通讯录中的数据自然就不存在了,等下次运行通讯录程序的时候,数据又得重新录入,如果使用这样的通讯录就很难受。在编写程序的时候,在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指针和文件的关系。每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息,(如文件的名字,文件状态及文件当前的位置等)。
2023-04-08 19:51:49
322
原创 C语言——动态内存管理(2)经典笔试题+柔性数组
在前面我们学过结构体的大小是内存对齐,联合的大小是共用一块空间,先求出各自的内存对齐大小,再减去联合体最大成员的数据类型即可,那么我们看看柔性数组的大小。但是被static修饰的变量存放在数据段(静态区),数据段的特点是在上面创建的变量,直到程序。实际上普通的局部变量是在栈区分配空间的,栈区的特点是在上面创建的变量出了作用域就销毁。realloc是调整申请的堆区内存的大小的,其实也可以像malloc一样申请开辟空间。C99 中,结构中的最后一个元素允许是未知大小的数组,这就叫做『柔性数组』成员。
2023-03-30 22:58:28
304
2
原创 C语言——字符串函数(2)和内存函数
memcpy函数的返回类型是void*指针,因为memcpy设计者,不知道程序员使用memcpy拷贝什么类型的的数据,void*指针——通用类型指针,可以接受任意类型数据的地址。因为数组的地址是从低地址到高地址存放的,所以我们将目的地指针与源头指针比较,就能实现从前->后 或者从后->前的交换方式,分成区间来解决,完美模拟了memmove函数的实现。strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。如果分隔符太多,难道我们要一直写下去吗?
2023-03-26 19:52:13
293
1
原创 C语言——字符函数和字符串函数(1)
当s2等于\0时就返回cp就即可,这样又记录了相等的起始位置cp,又没有改变cp的位置,又遍历了s1和s2字符串数组,如果找不到就返回空指针NULL。1.字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )。当给自己追加的时候,自己给自己追加的时候 \0被覆盖 源头也没\0 相当于字符数组 找到\0才停止 所以会乱码 相当于随机值。这个追加的是 它是追加完自动补充\0还是原有的\0,但我们不清楚,所以我们可以测试一下。
2023-03-26 14:36:59
376
原创 C语言——动态内存管理
2.原有空间之后没有足够大的空间:原有空间之后没有足够多的空间时,扩展的方法是:在堆空间上另找一个合适大小的连续空间来使用。返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。,1.当原有空间之后有足够大的空间:要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发生变化,函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为0。如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
2023-03-25 18:07:33
237
3
原创 C语言——自定义类型详解(1)
我们知道C语言中有int 、char、 long 、float 、double内置数据类型,自定义类型就是:允许自己创造一些类型,自定义类型:结构体、枚举、 联合体等....在传输数据的时候,把字节弄小,可以更好的传输信息,不会堵塞。结构是一些值的集合,这些值称为成员变量。一周的星期一到星期日是有限的7天,可以一一列举。数据结构:描述的是数据在内存中的存储结构。结构体的内存对齐是拿空间来换取时间的做法。在声明结构的时候,可以不完全的声明。2.结构体(结构的声明与基础知识),以此类推,到最后一个数据的时候,
2023-03-19 16:22:14
598
1
原创 C语言——最大公约数和最小公倍数求法
两个数的乘积等于这两个数的最大公约数与最小公倍数的乘积。假设有两个数是a、b,它们的最大公约数是p,最小公倍数是q。那么有这样的关系:ab=pq。最小公倍数与最大公约数是倍数关系,最小公倍数总是最大公约数的倍数,最大公约数是最小公倍数的约数。辗转相除法:欧几里得算法又称辗转相除法,是指用于计算两个。我们要求最大公约数的之前,先科普一下辗转相除法。在此之前,科普一下最大公约数和最小公倍数的关系。1.最大公约数的求解方法。有数学和计算机两个方面。2.最小公倍数的求解方法。
2023-03-09 21:55:25
1119
原创 qsort函数的使用与自我实现
当我们void*base不知道接受什么类型的数据时,我们把void*base强制类转换成char类型然后再相加j的值再相乘width的值,就可以知道我们接受的是什么类型的数据,然后再一个字节一个字节的交换,可以完成整个数组类型元素的交换,成功实现qsort函数的自我实现。size_t num是指向的是要数组的元素个数,size_t是无符号数,因为qsort函数不保证接受的所有数都是整数,也可能有负数,整成无符号数更便利于计算机的计算和程序的执行。4.qsort函数的自我实现。3.qsort函数的使用。
2023-03-09 16:03:08
130
原创 C语言——指针进阶
通过计算&arr+1地址是D54和计算结果相同,所以.&arr -这里的数组名表示整个数组,取出的是整个数组的地址,从地址值的角度来讲和数组首元素的地址是一样的,但是意义不一样。3.指针是有类型的,指针的类型决定了指针的+ -整数的步长,指针解引用操作的时候的权限。如果是指针,传过去的是第一行的地址,形参就应该是数组指针 int(*arr)[5]。一维 数组传参,形参可以是数组,也可以是指针的,当形参是指针的时候,要注意类型。实际上:&arr表示的是数组的地址,而不是首元素的地址。(五)数组指针的使用。
2023-03-05 00:27:56
152
原创 “C语言“——深度剖析浮点型在内存中的存储
知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;举例子来说,(5.5)10进制转换成二进制,应该是101.1,因为5是10的负一次方乘5,等于2分之1,0.5在计算机中算1,所以(5.5)十进制转换二进制就是101.1。对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。对于32位的浮点数,最高的1位是符号位s,接着的8位是指数E,剩下的23位为有效数字M。
2023-03-03 23:32:34
143
1
原创 C语言——初阶指针
方框上面的是变量自己的地址,方框里面的是取的是解引用变量的地址,把&a的地址存到pa地址中,再把原来pa自己的地址存到ppa的地址中。无论是什么类型指针,取出的地址永远是最小字节的地址,从运行结果可以看出来pc和pi的值是有一模一样的,而pc+1从B4变成了B5,pi+1从B4变成了B8。假设把10放进一个内存单元中,int是4个字节的,所以站4个字节空间,而&a取地址是取的最小的地址,就是第一个内存单元的地址。在32位的机器上,地址是32个0或者1组成二进制序列,那地址就得用4个字节的空间来存储,所以。
2023-02-19 22:35:08
85
原创 C语言——操作符详解(1)
CSDN的同学们大家好!,今天的讲解内容是C语言中一些操作符的使用和注意方法,ok,let‘s go!(一)算术操作符算术操作符有:+ - * / %
2023-02-14 13:12:52
111
2
原创 计算机——常用数制及转换
其中,二进制的一个数位是存储数据的最小单位,其值为或者0,称为位(bit)。若要将二进制、八进制、十六进制等非十进制数转换为十进制数,只需将给定的非十进制数按权展开,按照求和的形式就可计算出相应的十进制数。十六进制的基数为16,它有8个数码:0,1,2,3,4,5,6,7,8,9,A,B , C , D , E, F。通常其最高位(左边第一位)位符号位,0表示正数,1表示负数,其余位为数值位。十进制数整数部分从小数点起自右向左记录位数,个位记为0,十位记为1,百位记为2,照此类推。不同为1 相同为0。
2023-02-13 13:59:29
3467
5
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人