- 博客(22)
- 收藏
- 关注
原创 栈和队列(小白版)
栈的实现可以采取链表和数组两种形式,但是栈遵循后进先出(先进后出)的原则,要想节约空间、提高效率,应当采用数组作为栈的底层实现方式,因为数组在尾上插⼊数据的代价⽐较⼩。队列的实现方式和栈其实是很相似的,都是可以采取数组和链表作为底层实现形式,但这两个的时间复杂度都不太好,因此可以想到用一个结构体来直接包含队列的头和尾。压栈:栈的插⼊操作叫做进栈/压栈/⼊栈,⼊数据在栈顶。出栈:栈的删除操作叫做出栈。
2025-01-25 15:00:03
269
原创 二、单链表
图中指针变量plist保存的是第⼀个结点的地址,我们称plist此时“指向”第⼀个结点,如果我们希望plist“指向”第⼆个结点时,只需要修改plist保存的内容为0x0012FFA0。这里不用像上面那样要判断该链表是否为空,因为上面是尾插,也就是要找到链表的尾部在进行插入,而这个是头插,就算该链表是空的,也只是将newnode中的next变为NULL。链表中每个结点都是独⽴申请的(即需要插⼊数据时才去申请⼀块结点的空间),我们需要通过指针变量来保存下⼀个结点位置才能从当前结点找到下⼀个结点。
2025-01-14 20:36:39
431
原创 一、顺序表
但是在物理结构上并不⼀定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。本文主要有一个头文件,两个源文件,会把函数的声明放在头文件中,这样就可以使函数在一个源文件中实现后,直接在另一个源文件中使用。上面是函数的实现,如果想要使用这些函数,就需要在创建一个源文件,其中包含int main这个主函数,在进行使用。概念:顺序表是⽤⼀段物理地址连续的存储单元依次存储数据元素的线性结构,⼀般情况下采⽤数组存储。顺序表的底层结构是数组,对数组的封装,实现了常⽤的增删改查等接⼝。
2024-12-04 11:47:50
569
原创 函数栈帧的创建和销毁
我们在写C语言代码的时候,经常会把一个独立的功能抽象为函数,所以C程序是以函数为基本单位的。那函数是如何调用的?函数的返回值又是如何待会的?函数参数是如何传递的?这些问题都和函数栈帧有关系函数参数和函数返回值临时变量(包括函数的非静态的局部变量以及编译器自动生产的其他临时变量)保存上下文信息(包括在函数调用前后需要保持不变的寄存器)
2024-12-01 23:30:46
1403
原创 算法复杂度
空间复杂度 O(1)这个方法叫做三逆序法• 前n-k个逆置:5 6 7 4 3 2 1• 后k个逆置 :4 3 2 1 7 6 5• 整体逆置 : 5 6 7 1 2 3 4begin++;end--;
2024-11-30 23:34:53
1397
原创 预处理详解
C语⾔设置了⼀些预定义符号,可以直接使⽤,预定义符号也是在预处理期间处理的__FILE__ //进⾏编译的源⽂件,打印要用字符串__LINE__ //⽂件当前的⾏号 ,%d__DATE__ //⽂件被编译的⽇期 %s__TIME__ //⽂件被编译的时间 %s__STDC__ //如果编译器遵循ANSI C,其值为1,否则未定义1000register//为 register这个关键字,创建⼀个简短的名字for;;//⽤更形象的符号来替换⼀种实现break;case。
2024-11-28 13:01:38
1149
原创 编译和链接
编译器所能做的分析是语义的静态分析。3、处理#include预编译指令,将包含的头⽂件的内容插⼊到该预编译指令的位置。这个过程是递归进⾏的,也就是说被包含的头⽂件也可能包含其他⽂件。将源代码程序被输⼊扫描器,扫描器的任务就是简单的进⾏词法分析,把代码中的字符分割成⼀系列的记号(关键字、标识符、字⾯量、特殊字符等)编译过程就是将预处理后的⽂件进⾏⼀系列的:词法分析、语法分析、语义分析及优化,⽣成相应的汇编代码⽂件。注:在Windows环境下的⽬标⽂件的后缀是.obj ,Linux环境下⽬标⽂件的后缀是.o。
2024-11-27 23:23:19
1162
原创 文件操作.C
每个被使⽤的⽂件都在内存中开辟了⼀个相应的⽂件信息区,⽤来存放⽂件的相关信息(如⽂件的名字,⽂件状态及⽂件当前的位置等)。如果没有⽂件,我们写的程序的数据是存储在电脑的内存中,如果程序退出,内存回收,数据就丢失了,等再次运⾏程序,是看不到上次程序的数据的,如果要将数据进⾏持久化的保存,我们可以使⽤⽂件。⽂件的内容不⼀定是程序,⽽是程序运⾏时读写的数据,⽐如程序运⾏需要从中读取数据的⽂件,或者输出内容的⽂件。在以前各章所处理数据的输⼊输出都是以终端为对象的,即从终端的键盘输⼊数据,运⾏结果显⽰到显⽰器上。
2024-11-24 21:07:26
1316
原创 动态内存管理
有时会我们发现过去申请的空间太⼩了,有时候我们⼜会觉得申请的空间过⼤了,那为了合理的使⽤内存,我们⼀定会对内存的⼤⼩做灵活的调整。当是情况2的时候,原有空间之后没有⾜够多的空间时,扩展的⽅法是:在堆空间上另找⼀个合适⼤⼩的连续空间来使⽤。当是情况1的时候,要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发⽣变化,这种情况可能返回的还是原来指针的地址。包含柔性数组成员的结构⽤malloc()函数进⾏内存的动态分配,并且分配的内存应该⼤于结构的⼤⼩,以适应柔性数组的预期⼤⼩。
2024-11-22 00:02:47
1033
1
原创 ⾃定义类型:联合和枚举
i在这里是00 00 00 01,如果是小端的话c就是01,那这个函数就会返回1了,如果是大端的话c就是00,那就返回0了。联合的成员是共⽤同⼀块内存空间的,这样⼀个联合变量的⼤⼩,⾄少是最⼤成员的⼤⼩(因为联合⾄少得有能⼒保存最⼤的那个成员)像结构体⼀样,联合体也是由⼀个或者多个成员构成,这些成员可以不同的类型。当最⼤成员⼤⼩不是最⼤对⻬数的整数倍的时候,就要对⻬到最⼤对⻬数的整数倍。⼀周的星期⼀到星期⽇是有限的7天,可以⼀⼀列举。性别有:男、⼥、保密,也可以⼀⼀列举。联合的⼤⼩⾄少是最⼤成员的⼤⼩。
2024-11-21 19:35:42
441
原创 ⾃定义类型:结构体
再说s4,c1放到0处,但s3不是放到16的倍数处,而应该是放到s3中double d默认对齐数的整数倍处,也就是8的地方,那s4中d的开始位置就是24,所以总体大小就是32,又刚好是8的倍数。位段和前面结构体中变量的定义不一样,这里定义的是_a这个变量所占有的bit个数,但是要注意不要超过本身类型的bit位个数,就比如说int类型,就不能超过32位。如果嵌套了结构体的情况,嵌套的结构体成员对⻬到⾃⼰的成员中最⼤对⻬数的整数倍处,结构体的整体⼤⼩就是所有最⼤对⻬数(含嵌套结构体中成员的对⻬数)的整数倍。
2024-11-21 10:00:49
740
原创 数据在内存中的存储
⽐如保存1.01的时候,只保存01,等到读取的时候,再把第⼀位的1加上去。但是,我们知道,科学计数法中的E是可以出现负数的,所以IEEE754规定,存⼊内存时E的真实值必须再加上⼀个中间数,对于8位的E,这个中间数是127;⽐如:0.5的⼆进制形式为0.1,由于规定正数部分必须为1,即将⼩数点右移1位,则为1.0*2^(-1),其阶码为-1+127(中间值)=126,表⽰为01111110,⽽尾数1.0去掉整数部分为0,补⻬0到23位00000000000000000000000,则其⼆进制表⽰形式为。
2024-11-17 15:07:18
644
原创 C语⾔内存函数
其实,我们可以发现memcoy和strncpy这两个函数很像,都是对数据的拷贝,但strncpy是只适用于对字符串的拷贝,而memcpy可用于任何类型数据的拷贝。1、函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。1、和memcpy的差别就是memmove函数处理的源内存块和⽬标内存块是可以重叠的。3、 如果source和destination有任何的重叠,复制的结果都是未定义的。⽐较从ptr1和ptr2指针指向的位置开始,向后的num个字节。
2024-11-17 10:53:08
438
原创 字符函数和字符串函数
仔细看,可以发现他比strcpy多了一个n,这里的n可以理解为number的意思,其实这两个函数的功能是很类似的,但是strncpy多了一个限制,限制其一次性可以复制的数量。islower 是能够判断参数部分的c是否是⼩写字⺟的,通过返回值来说明是否是⼩写字⺟,如果是⼩写字⺟就返回⾮0的整数,如果不是⼩写字⺟,则返回0。strcat 函数是 C 语言标准库中的一个字符串处理函数,用于将一个字符串(源字符串)连接到另一个字符串(目标字符串)的末尾。第⼀个字符串⼩于第⼆个字符串,则返回⼩于0的数字。
2024-11-13 10:33:07
938
原创 (简单版)指针五
如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被⽤来调⽤其所指向的函数时,被调⽤的函数就是回调函数。回调函数不是由该函数的实现⽅直接调⽤,⽽是在特定的事件或条件发⽣时由另外的⼀⽅调⽤的,⽤于对该事件或条件进⾏响应。我们平常对数组中的元素进行排序,要么是普通排序,要么就是利用算法,比如说前面学习的冒泡排序,但是我们发现对于一些字符串数组或者是结构数据来说,排序是异常困难的,而qsort这个函数就是专门用来排序的,什么类型的都可以。calc这个函数通过获取加减乘除函数的地址来进行调用其函数。
2024-11-12 22:36:13
314
原创 (简单版)指针4
根据数组名是数组⾸元素的地址这个规则,⼆维数组的数组名表⽰的就是第⼀⾏的地址,是⼀维数组的地址。根据上⾯的例⼦,第⼀⾏的⼀维数组的类型就是int [5] ,所以第⼀⾏的地址的类型就是数组指针类型int(*)[5]。那就意味着⼆维数组传参本质上也是传递了地址,传递的是第⼀⾏这个⼀维数组的地址,那么形参也是可以写成指针形式的。解释:p先和星号结合,说明p是⼀个指针变量,然后指针指向的是⼀个⼤⼩为10个整型的数组。函数是有地址的,函数名就是函数的地址,当然也可以通过&函数名 的⽅式获得函数的地址。
2024-11-12 13:00:36
514
原创 冒泡排序(详细讲解)
首先,先文字讲解,这里总共有十个数据,而我们每次排序都会将一行中大的数据移到右边去,所以总共要进行10-1=9次循环,而在每一次循环中,又要连续对相邻的两个数据进行比较,但你会发现,随着循环次数的变多,进行比较的次数就会随之变小,因此我们的代码就可以这么写。但可以对改代码还能进一步优化,如果该数据在其中一组循环中已经按照从小带大的顺序拍好了,那是不是就可以不用再进行后面的循环了?你想对这些数据进行从小到大的排序,一个个用if和else去进行比较太麻烦了,所以这时候冒泡排序就可以帮你提高效率。
2024-11-10 14:22:54
497
原创 简单版(指针三)
这⾥我们使⽤&arr[0] 的⽅式拿到了数组第⼀个元素的地址,但是其实数组名本来就是地址,⽽且是数组⾸元素的地址,我们来做个测试。数组名是数组⾸元素的地址;那么在数组传参的时候,传递的是数组名,也就是说本质上数组传参传递的是数组⾸元素的地址。通过运行,我们发现他们的结果是一样的,因此,我们可以记作数组名就是数组⾸元素(第⼀个元素)的地址。总结:⼀维数组传参,形参的部分可以写成数组的形式,也可以写成指针的形式。我们知道一级指针是指向变量的地址,那指针变量的地址存放在哪⾥?我们可以使用指针来获取数组中的内容。
2024-11-10 13:49:37
352
原创 (简单版)指针二
变量是可以修改的,如果把变量的地址交给⼀个指针变量,通过指针变量的也可以修改这个变量。上述代码中n是不能被修改的,其实n本质是变量,只不过被const修饰后,在语法上加了限制,只要我们在代码中对n就⾏修改,就不符合语法规则,就报错,致使没法直接修改n。这时候却发现n被修改了,这是因为我们绕过n,使⽤n的地址,去修改n,虽然这样做是在打破语法规则,那我们想要防止这种做法怎么办?简单来说,就是const放在*的左边表示指针所指向的内容不能被修改,被钉死了的,但指针本身却可以修改,也就是地址,举个例子。
2024-11-09 17:06:51
716
原创 (简单版)指针一
而对到计算机中,我们知道计算机上CPU(中央处理器)在处理数据的时候,需要的数据是在内存中读取的,处理后的数据也会放回内存中,那我们买电脑的时候,电脑上内存是8GB/16GB/32GB等,那这些内存空间如何⾼效的管理呢?指针可以+1,那也可以-1。举一个生活中的例子,如果你要在一栋楼中找一个房间,一个一个的去寻找肯定很浪费时间,而如果告诉你房间号,就能提⾼效率,能快速的找到房间。上述的代码就是创建了整型变量a,内存中申请4个字节,⽤于存放整数10,其中每个字节都有地址,可以通过VS中的调试自己查看。
2024-11-08 23:40:26
503
原创 来优快云第一天
大家好,这是我来优快云的第一天,我不知道自己能坚持多久,但我会尽己所能的去努力!我暂时还没什么编程目标(因为太菜了),但我想先学习完C和C++在做一个长远的规划。对于学习的过程,我就是想一边跟着鹏哥一起学,一边自己刷题。我的目标就是进入华为,努力加油只为了能看到更好的风景。我会在编程上尽可能得多花时间,一天最少两个小时。
2024-10-26 23:39:10
124
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人