自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 手撕排序2--选择排序(直接选择+堆排序

把最大的换到最后,不把其看做是堆里的。前n-1个数向下调整,选出次大的数,再跟倒数第二个位置交换........每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。堆排序是利用堆 这种数据结构而设计的一种排序算法,它是选择排序的一种。将该节点与左右子树的节点进行比较,重新构建成一个大堆或者小堆。每个结点的值都小于或等于其左右孩子结点的值,称为。每个结点的值都大于或等于其左右孩子结点的值。物理结构是:一个数组。1. 对待排序的数组,先构建成 堆。

2024-06-21 23:28:17 509

原创 手撕排序1---插入排序(C 直接插入+希尔排序

gap不断减小,当gap为1时相当于直接插入排序,进行最后一次直接插入排序后数列便已有序。,gap越大,大的数可以越快到后面,小的数可以越快到前面。gap越小,越接近有序。先选定一个整数gap,把待排序数列中所有记录分成个gap个组,然后缩小gap,可以取它的一半,重复上述分组和排序的工作。预排序可以 让大的数更快地到序列后面,小的更快到前面。,直到所有的记录插入完为止,得到一个新的有序序列。的排序码与arr[i-1],arr[i-2],…当gap到达1时,该数列便已有序。,并对每一组内的记录进行排序。

2024-06-18 18:31:57 409

原创 数据结构--力扣104,110 二叉树相关(C

求其 左子树和右子树的最大深度,返回其中最大值即可。左右子树 高度之差的绝对值 不超过1。左子树和右子树 都是平衡二叉树。叶子结点 指:没有子节点的节点。

2024-06-16 13:21:42 322

原创 数据结构--力扣144.二叉树的前序遍历(C

【代码】数据结构--力扣144.二叉树的前序遍历(C。

2024-06-15 13:29:31 237

原创 数据结构---力扣232.用栈实现队列(C

代码中 栈 的基本实现,不在以下展示,参考之前的文章。入s1: (4.3.2.1)让一个栈(s1)作为空栈,入队列的栈。另一个(s2)作为非空栈,出队列的栈。从s1进到s2: (1.2.3.4)栈 是 后进先出。队列 是 先进先出。假设 1.2.3.4。

2024-06-11 23:43:46 457

原创 数据结构---力扣225.用队列实现栈(C

代码中 队列 的基本实现,不在以下展示,参考之前的文章。把不为空的队列数据导出,直到剩最后一个。(始终保持一个队列为空的思路)栈 是 后进先出。往 不为空的队列 中入。队列 是 先进先出。

2024-06-11 17:24:44 361 2

原创 数据结构---力扣 20.有效的括号 (C语言

代码中 栈 的基本实现,不在以下展示,参考上一篇文章。2.右括号-- 判断出栈顶的左括号与右括号是否匹配。使用 栈 来完成操作。1.左括号-- 入栈。

2024-06-07 09:19:36 268

原创 数据结构--栈和队列(详解+代码实现

/获取栈中有效元素个数。2.队中的元素不做修改,只能在队头删除,队尾增加元素。1.先进入栈的元素 会放在栈的底部。

2024-06-06 15:35:55 860 1

原创 C 贪吃蛇小游戏 (附代码

游戏结束(GameEnd)完成游戏结束的说明,实现资源释放。程序开始就设置程序⽀持本地模式,然后进⼊游戏的主逻辑。蛇吃食物的功能 (上、下、左、右方向键控制蛇的动作)游戏运行(GameRun)完成游戏运行逻辑的实现。游戏开始(GameStart)完成游戏的初始化。

2024-05-27 19:06:49 480 1

原创 数据结构---双向链表(附代码

传一级存在的问题是,当phead置为NULL后,实参plist不会被修改为NULL,LTDestory和LTErase参数为什么不传二级指针?带头:指的是链表中有哨兵位节点,该 哨兵位节点 即 头节点。理论上是要传二级指针的,因为我们需要让形参的改变影响到实参。哨兵位节点不存储任何有效元素,只是站在这里“放哨的”“哨兵位”存在的意义: 遍历循环链表避免死循环。因此解决办法是:调用完方法后,手动将实参置为空。2.双向链表(带头双向循环链表) 结构。:尾节点的next指针指向头节点。:单向不带头不循环链表。

2024-05-17 10:49:13 341

原创 单链表经典算法OJ题--牛客(环形链表的约瑟夫问题

在罗马人占领乔塔帕特后,39 个犹太⼈与 Josephus及他的朋友躲到⼀个洞中,39个犹太⼈决定宁愿死也不要被⼈抓到,于是决定了⼀个自杀方式,41个⼈排成⼀个圆圈,由第1个⼈开始报数,每报数到第3人,该人就必须自杀,然后再由下一个重新报数,直到所有⼈都自杀身亡为止。然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在 第16个与第31个位置,于是逃过了这场死亡游戏。

2024-05-15 12:55:22 398

原创 单链表经典算法 面试题--力扣02.04

greaterTail大链表的尾结点的next指针指向NULL。将小链表的尾结点与大链表的第一个有效的 节点首尾相连。将pcur节点小于x的值,尾插在小链表中。否则代码会出现死循环--【超出时间限制】创建新链表:大链表和小链表。3.判断链表是否为空。

2024-05-15 11:34:44 297

原创 单链表经典算法OJ题---力扣21

创建新的空链表,遍历原链表。将节点值小的节点拿到新链表中进行尾插操作。//此时链表不为空,头尾指针都指向了一个有效的地址(节点)在n1,n2去尾插过程中存在重复代码。遍历的结果只有两种情况:n1为空 或 n2为空。优化后的版本实行起来,也可通过。代码实现:【下面有进行优化】注意:链表为空的情况。

2024-05-13 16:25:48 255

原创 单链表经典算法OJ题---力扣206,876(带图详解

n3如果为空,则不能继续指向下一节点,需要进行判断。【slow每次走1步,fast每次走2步】在奇数个节点中成立,偶数个节点中也是可行的。

2024-05-12 22:47:55 489 1

原创 单链表经典算法LeetCode--203.移除链表元素(两种方法解)

需要注意:在跳出循环后,将newTail指向下一个节点的指针置为空。定义一个pcur指针指向头节点,定义一个prev指针指向NULL。定义newTail指针进行尾插。,定义pcur指针进行遍历。链表中有连续的val。

2024-05-12 12:01:19 373 1

原创 数据结构--单链表 详解(附代码

图中指针变量 plist保存的是第⼀个节点的地址,我们称plist此时“指向”第⼀个节点,链表中的每个节点都是独立申请的(即需要插⼊数据时才去申请⼀块节点的空间),我们需要通过指针变量来保存下⼀个节点位置才能从当前节点找到下⼀个节点。---- 一级指针也就是phead,当链表为空的时候,phead就是为NULL,而二级指针永远指向phead,phead的地址是永远存在的,那么pphead就一定不可能为空,所以需要断言pphead。,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。

2024-05-11 19:40:09 455

原创 顺序表经典算法OJ题-- 力扣27,88

题1:移除元素题2:合并两个有序数组作答: 作答:

2024-05-07 18:02:19 299

原创 数据结构---线性表(顺序表)附代码

假定数组有10个空间,已经使用了5个,向数组中插入数据步骤: 求数组的长度,求数组的有效数据个数,向下标为数据有效个数的位置插⼊数据(注意:这里是否要判断数组是否满了,满了还能继续插⼊吗)..... 假设数据量非常庞大,频繁的获取数组有效数据个数会影响程序执行效率。同理,程序中如果不对数据进行管理,可能会导致数据丢失、操作数据困难、野指针等情况。常见的数值1、2、3、4.....、教务系统里保存的用户信息(姓名、性别、年龄、学历等 )、网页里肉眼可以看到的信息(文字、图片、视频等等),这些都是数据。

2024-04-27 11:59:23 873

原创 C/C++中程序内存区域划分

1. 栈区(stack):在执⾏函数时,函数内局部变量的存储单元都可以在栈上创建,函数执⾏结束时 这些存储单元⾃动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内 存容量有限。栈区主要存放运行函数而分配的局部变量、函数参数、返回数据、返回地址等。2. 堆区(heap):⼀般由程序员分配释放, 若程序员不释放,程序结束时可能由OS(操作系统)回收。3. 数据段(静态区):(static)存放全局变量、静态数据。4. 代码段:存放函数体(类成员函数和全局函数)的⼆进制代码。

2024-04-18 15:07:57 457 2

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

所以,如果我们把结构体的内存以及其成员要的内存⼀次性分配好了,并返回给用户⼀个结构体指针,用户做⼀次free就可以把所有的内存也给释放掉。有时候我们需要的空间大小在程序运行的时候才能知 道,那数组的编译时开辟空间的方式就不能满足了。• 有时会我们发现过去申请的空间太小了,有时候我们又会觉得申请的空间过大了,那为了合理的申请内存,我们⼀定会对内存的大小做灵活的调整。• 包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。

2024-04-18 12:34:46 650 1

原创 C语言 | 自定义类型:联合和枚举

上述的结构其实设计的很简单,用起来也⽅便,但是结构的设计中包含了所有礼品的各种属性,这样 使得结构体的大小就会偏大,比较浪费内存。联合体的成员是共用同⼀块内存空间的,这样⼀个联合变量的大小,至少是最大成员的大小(因为联合 至少得有能力保存最大的那个成员)。这些可能取值都是有值的,默认从0开始,依次递增1,当然在声明枚举类型的时候也可以赋初值。• 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。在C语⾔中是可以的,但是在C++是不行的,C++的类型检查比较严格。

2024-04-16 17:50:46 643 1

原创 C语言 | 自定义类型:struct结构体(详解)

下图是网络协议中,IP数据报的格式,我们可以看到其中很多的属性只需要几个bit位就能描述,这里使用位段,能够实现想要的效果,也节省了空间,这样⽹络传输的数据报大小也会较小⼀些,对网络的畅通是有帮助的。4. 如果嵌套了结构体的情况,嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍。答案是不行的,因为Node是对前面的匿名结构体类型的重命名产⽣的,但是在匿名结构体内部提前使用Node类型来创建成员变量,这是不行的。

2024-04-15 18:42:53 1937

原创 数据在内存中的存储

这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着⼀个字节,⼀个字节为8 bit 位,但是在C语⾔中除了8 bit 的 char 之外,还有16 bit 的 short 型,32 bit 的 long 型(要看 具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于⼀个字节,那么必然存在着⼀个如何将多个字节安排的问题。,对于8位的E,这个中间数是127;对于64位的浮点数,最⾼的1位存储符号位S,接着的11位存储指数E,剩下的52位存储有效数字M。

2024-04-11 23:25:12 1568

原创 C语言 | 内存函数memcpy,memmove,memset,memcmp

• 和memcpy的差别就是memmove函数处理的源内存块和⽬标内存块是可以重叠的。1.复制的内容不同。• 从source的位置开始向后复制num个字节的数据到destination指向的内存位置。• memcpy用来做内存拷贝,你可以拿它拷贝任何数据类型的对象,可以指定拷贝的数据长度。• 如果source和destination有任何的重叠,复制的结果都是未定义的。• memset是用来设置内存的,将内存中的值以字节为单位设置成想要的内容。•第⼀个字符串大于第⼆个字符串,则返回大于0的数字。

2024-04-10 16:35:38 408

原创 C语言 | 字符函数和字符串函数

在不同的系统和C语⾔标准库的实现中都规定了⼀些错误码,⼀般是放在 errno.h 这个头⽂件中说明 的,C语⾔程序启动的时候就会使用⼀个全⾯的变量errno来记录程序的当前错误码,只不过程序启动 的时候errno是0,表⽰没有错误,当我们在使⽤标准库中的函数的时候发生了某种错误,就会讲对应 的错误码,存放在errno中,而⼀个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都是 有对应的错误信息的。• strtok函数找到str中的下⼀个标记,并将其⽤ \0 结尾,返回⼀个指向这个标记的指针。

2024-04-09 23:14:34 945 2

原创 C语言 | sizeof与strlen的区别(附笔试题)

如果操作数是类型的话,计算的是使用类型创建的变量所占内存空间的大小。统计的是从 strlen 函数的参数 str 中这个地址开始向后, \0 之前字符串中字符的个数。1. sizeof(数组名)--数组名表示整个数组,计算的是整个数组的大小,单位为字节。在X86(32位)环境下 假设结构体的大小是20个字节 程序输出的结果是啥?在学习操作符的时候,我们学习了 sizeof , sizeof为单目操作符。2. &数组名--数组名表示整个数组,取出的是整个数组的地址】内容多多,需耐心看完,加油!

2024-04-05 18:08:40 373 1

原创 C语言 | qsort()函数使用

目录:1.qsort介绍2.使⽤qsort函数 排序 整型数据3.使⽤qsort函数 排序 结构体数据4. qsort函数的模拟实现冒泡排序qsort()函数 是一个 C语言编译器函数库自带的它可以对指定数组(包括字符串,二维数组,结构体等)进行排序。

2024-03-25 23:45:17 1391

原创 C语言 | 函数指针变量&函数指针数组

根据前面学习整型指针,数组指针的时候,我们的类比关系,我们不难得出结论: 函数指针变量应该是用来存放函数地址的,未来通过地址能够调用函数的。确实打印出来了地址,所以函数是有地址的,函数名就是函数的地址,当然也可以通过 &函数名 的⽅ 式获得函数的地址。如果我们要将函数的地址存放起来,就得创建函数指针变量咯,函数指针变量的写法其实和数组指针非常类似。【在数组指针中,&数组名 是数组的地址。数组名是数组首元素的地址,两个地址的值是一样的。那要把函数的地址存到⼀个数组中,那这个数组就叫 函数指针数组。

2024-03-18 23:22:52 342

原创 二维数组 行遍历性能优于列遍历

因为这个数组比较小,CPU一次就可以把所有元素缓存,无论按行还是按列访问数组,CPU访问主存的数量都相同。-如果缓存中不存在需要的数据,系统将从主存或硬盘中读取数据,并将其存储到缓存中。在缓存中的数据是内存中的一小部分,但这一小部分是短时间内CPU即将访问的。如果存在,系统直接从缓存中读取数据,从而避免了访问主存或硬盘的开销,提高了访问速度。☝️随着数组元素越来越多,CPU缓存一次只能读取数组不到一行的数据,所以按列访问元素时,每访问一个元素都要访问内存,速度会慢很多。

2024-03-14 22:07:04 441 1

原创 C语言 | 字符指针

特别容易让同学以为是把字符串 abcdef 放到字符指针p2里了,☝️但是本质是把字符串 abcdef 的首字符的地址放到了p2中。这里str3和str4指向的是同⼀个常量字符串。C/C++会把常量字符串存储到单独的⼀个内存区域, 当几个指针指向同⼀个字符串的时候,他们实际会指向同⼀块内存。但是⽤相同的常量字符串去初始化不同的数组的时候 就会开辟出不同的内存块。在指针的类型中我们知道有⼀种指针类型为字符指针 char*p1指向的是字符数组,数组的内容是可变的。p2指向的是常量字符串,其内容不能修改。

2024-03-13 23:29:12 329

原创 C语言 | 数组指针与指针数组

解释:p先和*结合,说明p是⼀个指针变量,然后指向的是⼀个⼤⼩为10个整型的数组。所以 p是⼀个指针,指向⼀个数组,叫 数组指针。arr[i]是访问arr数组的元素,arr[i]找到的数组元素指向了整型⼀维数组,arr[i][j]就是整型⼀维数组中的元素。上述的代码模拟出⼆维数组的效果,实际上并⾮完全是⼆维数组,因为每⼀⾏并⾮是连续的。这⾥要注意:[ ]的优先级要高于*号的,所以必须加上()来保证p先和*结合。那数组指针应该是:存放数组的地址,能够指向数组的指针。整型数组,是存放整型的数组,

2024-03-12 22:59:06 371 1

原创 C语言 | 冒泡排序(小优化)

☝️而例如:9 0 1 2 3 4 5 6 8 7 要按从小到大输出。第一次循环:进行9次比较,将9(最大的)放在最后一位。在之前的文章中有说过冒泡排序。

2024-03-11 13:14:27 338 1

原创 C语言 | 数组传参

所以本质上p[i] 是等价于 *(p+i),同理arr[i] 应该等价于 *(arr+i),数组元素的访问在编译器处理的时候,也是转换成⾸元素的地址+偏移量求出元素的地址,然后解引⽤来访问的。那么在数组传参 的时候,传递的是数组名,也就是说数组传参 本质上传递的是数组⾸元素的地址。, 这里的数组名表示整个数组,取出的是整个数组的地址(整个数组的地址和数组⾸元素的地址是有区别的)1,数组传参的本质是传递了数组首元素的地址,所以形参访问的数组和实参的数组是同一个数组。

2024-03-07 18:32:28 367 1

原创 C语言 | assert断言

🉑assert() 的使⽤对程序员是⾮常友好的,使⽤ assert() 有几个好处:它不仅能⾃动标识⽂件和 出问题的⾏号,还有⼀种⽆需更改代码就能开启或关闭 assert() 的机制。1️⃣⼀般我们可以在 Debug 中使⽤,在 Release 版本中选择禁⽤ assert 就⾏,在 VS 这样的集成开 发环境中,在 Release 版本中,直接就是优化掉了。assert.h 头⽂件 定义了宏 assert() ,⽤于在运⾏时确保程序符合指定条件,如果不符合,就报错终⽌运⾏。指明在什么文件,哪一行。

2024-03-04 20:06:05 330 1

原创 C语言 | 野指针

(我们可以把野指针想象成野狗,野狗放任不管是⾮常危险的,所以我们可以找⼀棵树把野狗拴起来, 就相对安全了,给指针变量及时赋值为NULL,其实就类似把野狗栓前来,就是把野指针暂时管理起来。对于指针也是,在使⽤之前,我们也要判断是否为NULL,看看是不是被拴起来起来的野狗,如果是不能直接使⽤,如果不是我们再去使⽤)当指针变量指向⼀块区域的时候,我们可以通过指针访问该区域,后期不再使⽤这个指针访问空间的 时候,我们可以把该指针置为NULL。0也是地址,这个地址是⽆法使⽤的,读写该地址 会报错。

2024-03-04 19:45:33 467 1

原创 C语言 | 指针运算

因为数组在内存中是连续存放的,只要知道第⼀个元素的地址,顺藤摸⽠就能找到后⾯的所有元素。大家还记得 strlen--求字符串长度 //统计的是字符串中\0之前的字符个数。(指针 - 指针 的绝对值 是 得到的两个指针之间的元素个数)我们知道 数组随着下标的增长,地址是由低到高变化。指针的大小比较 其实就是地址和地址的大小比较。(有关数组方面的问题,可在我的主页查找)计算的前提条件:两个指针指向了同一块空间。分享到这里,下期分享野指针.利用自定义函数 指针 完成。利用指针-指针的方法完成。

2024-03-03 12:18:49 429

原创 C语言| 指针变量

就是为了 不能被修改,如果p拿到n的地址就能修改n,这样就打破了const的限制,这是不合理的,所以应该让 p拿到n的地址也不能修改n,那接下来怎么做呢?在指针类型中有⼀种特殊的类型是 void* 类型的,可以理解为⽆具体类型的指针(或者叫泛型指 针),这种类型的指针可以⽤来接受任意类型地址。我们知道,32位机器假设有32根地址总线,每根地址线出来的电信号转换成数字信号后 是1或者0,那我们把32根地址线产⽣的2进制序列当做⼀个地址,那么⼀个地址就是32个bit位,需要4 个字节才能存储。

2024-03-02 11:10:57 803

原创 C语言|不创建临时变量,实现两个数的交换(面试)

但如果a和b都很大?加起来超出了整形的大小,发生溢出,可能就会出现bug。按二进制位进行运算,若两个二进制位相同,则结果为0,不同为1。所以知道 0^a = a a^a = 0。数据a的容器起到了周转数据的作用。先介绍一下:按位异或操作符 ^

2024-02-14 23:00:19 436 1

原创 扫雷小游戏| C语言(附代码

两个.c文件记得包含#include"saolei.h"排查之后,可得到4 4坐标周围8个坐标内存在一个雷。而当踩到雷被炸死后,会打印出雷的布局 结束一轮游戏。首先出现菜单选择界面:1为开始游戏,2为退出游戏。然后出现9*9棋盘界面,输入你要排查的坐标,要的数据类型和函数声明等。

2024-02-03 21:22:01 430 1

原创 C语言|指针(快速理解)

所以所有指针变量数据的宽度也为4字节,与指向的数据类型是无关的。(int*/char*/double*类型的指针变量都为4字节)我们都知道,数组在内存中的排列是线性的,所以我们可以通过一个指针指向这个数组的首地址,来进行操作。也就是说,指针和普通变量是一样的,可以赋值,可以运算,当然会比普通变量多一些使用方法。//更容易理解的写法(int*就是变量p的类型,p为变量名)使用函数传递参数时,直接传数据是不改变原变量的,而传地址就可以改变原变量。同理,在64位的程序中,指针变量的宽度为8字节。

2024-01-28 20:06:23 463 1

空空如也

空空如也

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

TA关注的人

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