自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(62)
  • 收藏
  • 关注

原创 递归实现斐波那契数列的空间复杂度的讲解

到左下的Fib(2)的时候,此时不同的Fib栈空间个数达到了最大,也就是n个栈空间,然后就会往回递归,并且往回递归的过程中还是重复利用之前的栈空间,所以空间复杂度应该是O(N)!),此时的Fib(1)会使用之前Fib(2)的栈空间,而不是额外的新的栈空间,然后Fib(1)达到了if的限制条件,然后回到了Fib(3)(此时的Fib(3)完全执行完毕,和最下面的Fib(2)执行完毕一样,此时执行完毕的Fib(3)会返回到上一级的Fib(4)(),然后Fib(2)执行完毕返回到上一级的Fib(4)(

2024-04-24 20:54:29 128

原创 冒泡排序的时间复杂度的讲解

遍历了n-1,n-2,n-3......才让数字来到该处于的位置,而这是一个等差数列(n-1,n-2,n-3......),该数列,首项为1,尾项为n-1,求和后,最大的影响项是n^2/2,所以时间复杂度为。最好就算是进来就是有序的,但是呢,它也得通过一遍的遍历才知道是否是有序的,所以还是n-1次,所以时间复杂度为O(n),而不是O(1)!只有两个数位置不对,就是n-1+n-2,也就是2n-3,也就是O(n)综上所述:时间复杂度为:O(n^2)。

2024-04-17 18:41:50 170

原创 二分查找的时间复杂度的讲解

所以x=log以2为底N的对数,简写成logN,在复杂度里面只有以2为底的可以简写,但是和数学里的lgN,没有任何的联系!因为最坏情况就是找不到和查找区间只剩一个值的时候,所以此时数据的个数就为1。综上所述:二分查找的时间复杂度为O(lgN)。由图可知:查找了多少次,就除了几次2。

2024-04-17 18:36:52 179

原创 消失的数字的两种巧妙方法

0^3然后去^下一个数,结果下一个数是4,3消失了,所以大致的流程变成了0^3(上面for循环没有消失的3)^4(下面for循环的3消失了,所以是4)^4(接着就是上面个for循环的4)^5v5.....,所以我们最后的x就变成了那个消失的数字,因为0^3^4^4^5^5就等同于0^3^0^0,也就是3。所以我们可以知道,如果两次for循环,x都面对同一个数,它会先变成这个数(0^a=a),然后再变成0(a^a=0),所以如果上下循环的数是同一个,x经过变换还是0。

2024-04-17 18:28:38 206

原创 scanf/fscanf/sscanf和printf/fprintf/sprintf的使用和对比

如果发生写入错误(例如,磁盘空间不足、文件无法访问等),则“错误指示器”(ferror)会被设置,并且函数会返回一个负数。它可能返回成功处理或填充的参数数量,这个数量可能与预期的数量相匹配,也可能更少。: 当尝试匹配某些内容(例如,从输入中查找特定的模式或字符串)时,可能会失败。: 如果函数试图读取文件,并且已经到达了文件的末尾,那么它将停止读取,并且返回的项目数量可能会少于预期。这个数量可能与预期的项目数量相匹配,但由于匹配失败、读取错误或达到文件末尾,它也可能更少(甚至为零)。

2024-03-30 16:03:09 805 1

原创 八种顺序读写函数的介绍(fput/getc;fput/gets;fscanf,fprintf;fwrite,fread)

(fput/getc;fput/gets;fscaf,fprintf;fwrite,fread)的使用介绍

2024-03-28 22:53:15 1067

原创 动态内存函数开辟的经典的笔试题

动态开辟内存忘记释放(内存泄漏)(一般是在某个函数中进行开辟,然后回到主函数,无法使用开辟的空间,导致泄露)(动态申请的内存空间,不会出了作用域就自动销毁(还给操作系统),只有free,或退出程序才能还给操作系统)。1,数组的创建,出作用域会销毁这个数组的内容,str的确指向了这个数组,但是已经变成了野指针,因为指向的空间已经不属于它了。: p的移动,导致了free的时候,不能够完全释放掉malloc开辟的全部内存。1,p只是str的一份临时拷贝,无法让str改变,因为采用给的是值的传递。

2024-03-27 15:25:59 206

原创 几种动态内存函数的理解(malloc,calloc,realloc,free)

函数的出现让动态内存管理更加灵活,有时会我们发现过去申请的空间太小了,有时候我们又会觉得申请的空间过大了,那为了合理的时候内存,我们一定会对内存的大小做灵活的调整。有时候我们需要的空间大小在程序运行的时候才能知道,那数组的编译时开辟空间的方式就不能满足了。的时候,原有空间之后没有足够多的空间时,扩展的方法是:在堆空间上另找一个合适大小的连续空间来使用,这样函数返回的是一个新的内存地址。1 的时候,要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发生变化,返回的是增加前的空间的首地址。

2024-03-27 14:58:25 789

原创 通讯录的模拟实现(增删查改,清空,排序)

联系人结构体要满足题目要求,另外我们还要创建一个通讯录结构体,其应该包含多个联系人结构体(联系人结构体数组)和联系人人数(sz),因为后面增加删除,以及联系人的访问都会用到sz,其次对几个重要变量的重定义,以后方便修改,不用去到处找修改的变量在哪里。text.c(大纲)的意义在于,明确整个程序的思路,程序开始,创建了一个通讯录,并且对其初始化为0,然后我们再让用户进行选择需要实现的功能,用switch case语句来实现多种功能。拥有增加,删除,搜索,修改,展示(所有联系人),退出功能。

2024-03-23 19:47:34 491 2

原创 如何用联合(共用体)union验证系统大小端

由联合体的特点,可知上图,char c 和 int i 共用四个字节,假设是小端,则由左到右是低地址到高地址,四个字节的内容如图所示01 00 00 00。如果第一个字节是1,则证明是小端,因为小端是指数据的低位保存在内存的低地址中,而数据的高位保存在内存的高地。

2024-03-22 15:09:37 335 1

原创 计算联合体union的大小

联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联。是最大成员的大小,也就是c数组的大小14,所以联合体最终的大小为离14最近的4。当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。是最大成员的大小,也就是c数组的大小5,所以联合体最终的大小为离5最近的4。所以Un1中c的对齐数是1,i的对齐数是4,所以最大对齐数是4,目前。所以Un2中c的对齐数是2,i的对齐数是4,所以最大对齐数是4,目前。的倍数,也就是16。

2024-03-21 17:00:28 387

原创 计算结构体的大小(结构体的内存对齐)

3,c2本身大小为1,而vs默认对齐数是8,所以1和8,进行比较,较小值为1,所以对齐数为1,那c2就要去找1的倍数处的地址(图中右边的数字),任何一个数都是1的倍数,所以就选择了紧接着i的红色格子。而c1和c2和i的对齐数中,最大的是4,所以结构体大小应该是4的倍数,因为此时结构体已经9个字节了,最近的符合规则的就是12,所以又往下浪费了3个字节。嵌套的结构体这个整体要对齐到自己的最大对齐数(也就是它内部元素的最大对齐数)的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

2024-03-21 16:36:05 290

原创 秒懂memmove的模拟实现

就是按照8,7,6,5,4的顺序复制给5,4,3,2,1,无法得到4,5,6,7,8,6,7,8,9,10(正确)而是得到7,8,6,7,8,6,7,8,9,10。,就是按照4,5,6,7,8的顺序复制给1,2,3,4,5,可以得到4,5,6,7,8,6,7,8,9,10(正确),就是按照4,5,6,7,8的顺序复制给6,7,8,9,10,可以得到1,2,3,4,5,4,5,4,5,4。,就是按照8,7,6,5,4的顺序复制给10,9,8,7,6,可以得到1,2,3,4,5,4,5,6,7,8。

2024-03-20 16:33:36 770 2

原创 memcpy的模拟实现

void* 类型的指针,不能进行指针运算和指针解引用,所以我们要将其进行强转之后再进行运算和解引用,那我们选择的强转的类型就是char*,逐字节的复制,会适用与多种类型指针的复制。因为返回的是dest指向的首地址,而dest指向的地址在复制的过程之中会被改变。3,因为不知道我们的源头数组和目的数组的类型,所以均用void * 来接收和返回,size_t num则是确保了复制的字节数是正数。的理解在于进行逐字节的复制,而num就是我们要复制的字节数,刚好作为循环条件。的内存位置,然后返回目的数组的起始地址。

2024-03-20 14:40:28 337

原创 字符串的左旋讲解

作用在于对于大于字符串长度的左旋,会%后再进行左旋,避免错误,左旋ABCDEFn个字符,代表左旋一个字符循环n次。将总体字符串BAFEDC再进行逆序,得到CDFEAB。a.先把第一个字符,用临时字符变量存起来。ABCDEF的左旋可以分为三步,以左旋。c.最后再将第一个字符赋给最后的字符。将后面剩下的字符逆序得到FEDC。b.然后后面的依次向前移动一个。要左旋几个字符,就循环几次即可。比如左旋7,其实就是左旋1。将前两个字符逆序得到BA。

2024-03-19 23:51:42 217

原创 杨氏矩阵的查找(复杂度<O(N))

如果n<它,代表最后一列也不用找了(因为它是第三列(最后一列)里面最小的)如果n>它,代表最开始一行已经不用查找了(因为它是第一行里面最大的):n>关键数,最开始一行不用找了,行+1。:n<关键数,最后一列不用找了,列-1。经过对行和列的不断变换,最终会找到n。被查找的数(n)与关键数进行比较。先找到一个最关键的数字,

2024-03-19 22:54:25 195

原创 strstr的模拟实现

所以我们要将str1和str2分别赋给一个新的字符指针,如图中的cp和s2,然后再将cp赋给s1,因为我们遍历比较的过程中,str1需要一个指针去遍历比较(s1),一个指针去指向某个可能首次出现str2位置(cp)。如果*s2为'\0'的时候,就代表已经在str1中找到了str2,因为不把s2的全部字符遍历完,不可能来到s2的'\0'。因为比较的过程中str1中的cp会因为比较的结果(比较不吻合)向后移动,当cp移动到最后一个字符'\0'的时候,也就代表再也在str1中找不到str2了,所以退出循环。

2024-03-17 21:32:02 508

原创 strcmp的模拟实现

因为e的ascll码值<f的ascll码值 ,返回小于0 的数子-1。因为两个字符串中对应的字符相等,所以一个不为'\0',另一个也不会。返还出正负或0值,直接return前者和后者的ascll码值即可。两个字符串中对应的字符相等就进入循环,否则肯定可以比较出大小。比较两个字符串的大小(按照字符串中字符的ascll码值)。第一个字符串大于第二个字符串,则返回大于。第一个字符串小于第二个字符串,则返回小于。断言是否为空指针,在考虑是否进行下一步。第一个字符串等于第二个字符串,则返回。

2024-03-15 21:02:32 311

原创 strcat的模拟实现

因为strcat返回值为拷贝后的目的数组的首地址,所以在函数内部一开始进行一次首地址的保留(char* start = dest;),因为之后首地址会改变。断言语句起到严谨的作用,先判断是不是空指针在考虑是否进入下一步。第二个while语句,简单,将赋值,判断,++,一气呵成。先找到目的数组中的 '\0' ,然后从 '\0'开始追加。目标空间必须有足够的大,能容纳下源字符串的内容。将源字符串追加(连接)到目的字符串的后面。然后返回目的数组的首地址(start)。进行最后一步 \0 的赋值。

2024-03-14 22:49:26 219

原创 strcpy的模拟实现

while语句先进行赋值(不管是不是\0,因为\0也需要赋值),然后判断赋值的结果是不是\0,因为\0 的ascll码值就是0(如果是的话,已经把\0赋值成功了,并且退出循环),然后进行后置的++,一气呵成。因为strcpy返回值为拷贝后的目的数组的首地址,所以在这里进行一次首地址的保留,因为之后首地址会改变(char* start = dest;源字符串第一个元素不是 \0 ,就进入循环,然后进行赋值,赋值完成后,地址双双往后移。返回值为拷贝完成后的目标数组的首地址。进行最后一步 \0 的赋值。

2024-03-13 21:28:53 285

原创 C语言打印菱形(三分钟教会)

line代表上半部分行(7行包括最中间那一行),所以上半部分为line(7)行,下半部分为line-1(6)行。这个菱形上半部分7行,下半部分6行。

2024-03-11 22:50:23 204

原创 数组名结合指针的面试题的讲解

这一步,aa为数组名,现在代表数组首元素地址,也就是一维数组1,2,3,4,5的首地址,然后+1.此时指向了第二个一维数组6,7,8,9,10的首地址,此时aa+1的类型是int(*)[5],然后就是对一个数组指针进行了解引用,所以结果是一个一维数组,然后又因为一维数组名代表首元素地址,也就是第一个元素6的地址,类型为int*,所以此时题目的将int*强转成int*是没有意义的,然后。(%p),是将-4以%p的形式打印,%p没有符号之分,直接将-4的补码以16进制进行打印。

2024-03-11 15:10:03 740

原创 数组名的理解,看这一篇就够了!!!

a[0]是这个一维数组的数组名,该数组名当单独放在sizeof中(sizeof(a[0])),或者前面&的时候(&a[0]),满足那两个条件,其所指的整个数组是它所对应的那一行数组,比如a[0]这个时候就代表第一行数组,a[1]这个时候就代表第二行数组.......现在对其进行+1-1,会以一行数组作为单位来跨越。a[0]作为第一行的数组名,没有单独放在sizeo内部,没有&,a[0]表示数组首元素的地址,也就是a[0][0]的地址,所以a[0]+1是第一行第二个元素的地址,是地址就是4/8个字节。

2024-03-10 20:35:58 633

原创 qsort函数的模拟实现

qsort函数会自己在比较大小之后去进行数组里面元素的位置的调换,而我们模拟实现要解决的就是这个问题,所以我们要自己创建函数去进行元素位置的调换。我们采用冒泡排序法来构建主题。

2024-03-09 21:40:47 175

原创 qsort函数的用法及参数的讲解

第四个参数,因为我们自己创建的比较整形的函数是 cmp_int,所以我们的传参传的就是cmp_int,函数名就是函数地址,所以和qsort函数的定义中的第四个参数为函数指针刚刚匹配,正好用函数指针来接收函数的地址(函数名)。指向一个比较两个元素的函数的指针(函数指针),这个函数将被qsort反复调用以比较两个元素,这个函数指针指向的函数,能够比较base指向数组中的两个元素。综上所述,所以我们要将void*强转为我们需要的指针类型,然后再解引用,才能得到我们所需要的数据。第三个:size_t size。

2024-03-09 19:36:47 657

原创 让你秒会C语言冒泡排序

j 就是控制每一趟的对比的对数,sz为10.多以

2024-03-09 17:30:28 157

原创 函数指针的理解与使用

输出的是两个地址,这两个地址都是 test 函数的地址。所以函数名前面加不加&都是可以获得该函数地址的。如果没括号:void *p (),则代表这是一个函数叫作p,参数为空,返回类型是void*。p先和*结合,说明p是指针,指针指向的是一个函数,指向的函数无参数,返回值类型为void。对函数取地址时候,不用&,函数没有首元素这个说法,它是一个整体,即ADD就是pf。前面是返回类型,后面是参数类型。将0作为这个函数的地址,然后调用,数字也可以作为地址!返回类型+(*)+(类型名)是函数指针类型。

2024-03-08 19:35:33 322

原创 让你秒懂浮点型在内存中的存储

第二问中是*pFloat的视角取出值,它必定认为这块空间里面放的是浮点数,同时它会以浮点数的形式取出,所以直接将 9 -> 0000 0000 0000 0000 0000 0000 0000 1001,用浮点数的规则来读取。这一步 ,是将浮点数存储到内存中去,先按照规则,写成二进制浮点数: 1001.0-------> (-1)^0 * 1.001 * 2^3。然后 % d 的形式去打印 ,这32位补码符号位为0,所以直接打印出结果:num的值为:1091567616。

2024-03-06 15:13:10 516

原创 让你秒懂对char和unsigned char 以%d或%u形式打印的核心

char的范围在-128~127,a【i】从-1递减开始1(-1,-2,-3)到-128,然后由图可知会从,127到0,总的来说,从-1~-128,然后从127~0,而strlen的判断条件是‘\0’,‘\0’的ascll码值就是0,所以在a【i】=0的时候,会停止,总计在0之前有255个数。%d是以有符号的形式打印整数,所以,我们整形提升后得到的32位补码,要先观察32的第一位,如果是1,则是负数,需要将这32位补码转化为原码(-1,符号位不变按位取反);如果是0,则是正数,原返补码相同,直接打印即可。

2024-03-06 12:44:21 1201

原创 手把手教你实现猜数字游戏

在使用rand之前,要先调用srand函数,srand是一个会初始化随机数的生成器,srand根据自己收到的参数的不同会返回不同的值,所以我们给srand函数传入时间戳,(给srand传入一个随时变化的值),而time函数的返回值,就是时间戳。可以看到,我们把switch语句放进了循环,我们玩家输入的变量为input,即使switch的变量,也是do while的判断条件,上来就打印一个菜单,然后说:请选择,玩家的选择,对应不同的case语句,并且也会用于循环的判断!b:猜小了,提醒猜小了,继续猜。

2024-01-11 12:47:13 333

原创 c初阶复习后三节课

scanf函数返回的是读取到的数据的个数,如果,scanf读取失败,会返回EOF,所以有时候可以while(scanf("%d",&a)==1),来循环一个程序,ctrl+z可以停止循环,让其返回eof。static修饰全局变量的时候,改变了全局变量的链接属性,不能在其他源文件内使用,只能在自己所在的源文件内使用。static修饰函数的时候,改变了函数的链接属性,不能在其他源文件内使用,只能在自己所在的源文件内使用。sizeof计算的是变量占有内存的大小,单位是字节,并且它不是函数,是一个操作符。

2024-01-08 19:34:45 297

原创 c初阶复习(前两节课)

define 定义的标识符 是一个真正的常量,如:#define size 10(本质在于给字面常量一个新的名字)全局变量的作用域很大,只要使用得当,任何地方都可以使用,但全局变量安全性不高,任何人都可以进行使用修改。strlen是库函数,用来求字符串长度的,从给定的地址,向后数字符个数,遇到\0结束,\0不计入个数。局部变量的生命周期,进入作用域开始(创建变量),出了作用域结束(销毁变量,归还空间)。const修饰的变量,虽然不能被修改,但是本身还是一个变量,所以叫常变量,而不叫常量。

2024-01-06 17:01:20 307 1

原创 C语言之编译与链接

每次使用宏的时候,一份宏定义的代码将插入到程序中。当宏参数在宏的定义中出现超过一次的时候,如果参数带有副作用,那么你在使用这个宏的时候就可能。用函数无法解决这个问题,一是语句中的字母无法替换,而是打印格式单一也无法替换。对于宏,参数名被他们的值所替换。定义中我们使用了括号,想避免之前的问题,但是这个宏可能会出现新的错误。这样就比较清晰了,由替换产生的表达式并没有按照预想的次序进行求值。这个问题,的解决办法是在宏定义表达式两边加上一对括号就可以了。种是翻译环境,在这个环境中源代码被转换为可执行的机器指令。

2023-09-10 16:12:11 60

原创 C语言之文件操作

每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。在以前各章所处理数据的输入输出都是以终端为对象的,即从终端的键盘输入数据,运行结果显示到显示器上。据,此时数据是存放在内存中,当程序退出的时候,通讯录中的数据自然就不存在了,等下次运行通讯。这就涉及到了数据持久化的问题,我们一般数据持久化的方法有,把数据存放在磁盘文件、存放到数据。的作用是:当文件读取结束的时候,判断是读取结束的原因是否是:遇到文件尾结束。

2023-09-09 15:00:42 34

原创 C语言之动态内存管理

问题:“hello world”的首地址在GetMemory结束前传给了str,但是里面的内容,在GM函数结束后,被回收了,有可能被别人使用了,所以打印的东西无法判断。有时候我们需要的空间大小在程序运行的时候才能知道, 那数组的编译时开辟空间的方式就不能满足了。直接将str的地址传给了函数,用二级指针接收,函数的操作才会影响到str,最后在Test函数内也进行了释放。的时候,原有空间之后没有足够多的空间时,扩展的方法是:在堆空间上另找一个合适大小。函数进行内存的动态分配,并且分配的内存应该大于结构的大。

2023-09-06 21:36:17 29

原创 C语言之自定义类型

10的二进制位只有三位保存到了a里面,以此类推,并且每一个字节要是不够下一个位段就会舍弃,如右图所示没有被黑色覆盖的就是被舍弃的部分,62 03 04。结构体创建变量的两种格式,前一种为主函数内创建,为局部变量,后一种为在{}后面创建,为全局变量。这些可能取值都是有值的,默认从0开始,依次递增1,当然在声明枚举类型的时候也可以赋初值。如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的。注意:根据对齐规则,应该是6,最大对齐数是4,8是4的倍数,所以结构体大小就是8。

2023-09-02 18:01:40 32

原创 C语言之内存函数

不同空间的数组,指针大小的判断的结果无关紧要,因为不重叠,走哪一个分支都会完成任务。2,如果源空间和目标空间出现重叠,就得使用memmove函数处理。根据源地址和目的地址的起始位置的前后来设置判断。函数处理的源内存块和目标内存块是可以重叠的。有任何的重叠,复制的结果都是未定义的。memcpy不适用与重叠内存的拷贝。的时候并不会停下来。原因:强转是临时的。

2023-09-02 13:10:39 19

原创 C语言之字符串函数讲解和模拟实现

若没有比较到某一方为\0,就停止,就代表两个字符不再相同,就退出循环,并且cp++,在对s1和s2进行新的位置更新,s1和新的cp一致,s2回到最初的str2。若有一个为\0,源字符串比较到了\0,就代表已经比较完成,并且都是一致,就返回cp的地址,即第一次出现子字符串的位置。除开两个地址,还需创建三个指针,对于目的字符串还要两个(cp s1),源字符串需要一个(s2)。不可以,字符串在追加的过程会将自己的/0覆盖,会无限制的追加,最后崩溃。中的下一个标记,并将其用\0 结尾,返回一个指向这个标记的指针。

2023-09-01 15:15:47 28

原创 数组名的解读

strlen的功能是返回字符串的长度,该字符串可能是自己定义的,也可能是内存中随机的,该函数实际完成的功能是从代表该字符串的第一个地址开始遍历,直到遇到结束符NULL。注意:a是首元素地址,将其强转为整形后,+1,即数字上的+1,即从40->41,然后又将其转化为int*,此时打印的就是之后的四个字节的内容,即绿框内的内容!sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节。&数组名,这里的数组名表示整个数组,取出的是整个数组的地址。,最后的表达式为其结果。

2023-08-31 21:05:14 91

原创 数组指针在一维二维数组中使用的对比

对函数取地址时候,不用&,函数没有首元素这个说法,它是一个整体,即ADD就是pf。在一维数组中使用数组指针去遍历每个元素,是一种,麻烦的方式。返回类型+(*)+(类型名)是函数指针类型。int (*)数字 是数组指针类型。3,一级指针的数组名(一级指针的地址)3,数组名(本质上是地址(首元素))1,数据类型取地址(&+数据类型)1,一级指针的地址(&p)二维数组更适用数组指针。

2023-08-30 15:05:57 32

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除