自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 栈和队列(1.栈)

先想清楚,我们是要用数组还是链表去实现这个结构。我们来分析一下使用数组和使用链表都有哪些优缺点。链表:先看看我们如果使用链表进行实现栈的插入和移出数据的操作,我们把头相像成栈底,插入还好说,也挺方便的。但是再进行移出操作的时候,你要删除的是尾部的数据,也就是尾插的时候,你得每次都去找尾结点,释放一次数据尾结点就找不到了,因为是使用单链表,你无法回溯上一个结点,所以每次都要遍历一遍,时间复杂度就会很高。数组:而数组就没有这个烦恼,不管是插入还是移出都很容易实现,所以我使用了数组去进行实现栈。当然链表也行。

2023-06-17 23:02:28 157

原创 带头双向链表

顾名思义,相比于单链表,带头双向链表就是本身自带头指针,链表的结构比单链表多一个用来指向前一个结点的地址的指针,如图:}ListNode;这双向链表虽然结构看起来稍微复杂一点,但是实现起来会非常简单。很简单,用malloc申请空间,将结构体里的指针都赋空值,数据传进来是啥就是啥,在这里头指针就无所谓值多少了,因为我们不会用到这个值,然后这个结构巧妙的地方的就是没有值的时候,头指针的prev和next都是指向自己的。所以就这样初始化。

2023-05-20 18:55:24 203

原创 结构体的变量的定义和初始化以及结构体大小的判断

char c;}s1;这里面struct S就是它的名字,s1是它的变量名。可以近似理解成struct S就相当于int,s1就相当于i。这样可能更好理解。int a;char c;}s1;s2;这个时候这里的s1和s2又分别是什么意思呢,注意这个时候s1不再是变量名了,因为struct前面加了个typedef,这个意思是把struct S给重命名为s1,而s2才是它的变量名。int a;char c;}s2;这样子也是可以的。

2023-04-04 17:44:40 932

原创 memcpy和memmove函数的理解和实现

我们都知道strcpy函数可以将字符串进行复制,那么其他数据类型是否也有函数可以进行复制。我今天讲的就是可以进行多种类型复制的函数memcpy。

2023-04-02 16:53:21 167

原创 指针2(指针和函数的碰撞)

第二种test:int * arr[5],有了第一种test的经验,很容易判断它就是对的,因为传进来的是一个一维数组的地址,数量是5个,那我就用一维数组arr[5]去接收这些元素,又因为传进来的是地址,所以是int *。我一个二维数组,你要么就用二维数组接收,要么就用指针去接收,用一个指针数组接收是什么意思,所以第二种test是错的第三种test:int (*arr)[5],这个就是对的了,首先先看看成分,它本质是一个指针,指向五个整形变量,是一个数组指针用来接收二维数组的传参是可以的。

2023-03-01 15:39:33 121

原创 指针进阶1(所含内容丰富详细,相信你一定会有所收获)

值得注意的是这个代码,这个代码的意思是把这个字符串首元素的地址放进pc,也就是说指针pc指向的是a的首地址,并不是整个字符串的地址。if语句里面判断是str1 == str2,这里str1和str2所代表的的并不是你的数组内容,而是‘h’的地址(数组名大部分情况下等于数组首元素地址),你也可能会说,两个都是‘h’地址不应该一样吗。同样的,理解什么是数组指针,我们来类比一下就知道了。看看这个语句,arr1是变量名,先跟[]结合,说明它是一个数组,剩下的int*就说明它的存放的类型是int*,也就是整形指针。

2023-02-23 12:11:41 104

原创 浮点型数据的存储和读取

先看前半部分,我们int 一个9,因为是正数所以原反补码相同,它在内存中就是这样表示的。然后用%d读取它,二进制转化回来还是9,而用float读取,第一位依旧是符号位,然后接下来8位就是E,这里E全为0,也就是真实值为-126。我们将同样的数据赋予不同的数据类型,它在内存中表达的数据自然就会不一样,当你用不同于你赋予的数据类型的方式去读取这个数据的时候,结果就会大大不同。的时,只保存01,1会自动补上去,这样本来只能存储22(51)位的,舍去1之后就留给小数点后的数据就多了一位,就更加精确了。

2023-02-22 11:30:48 450

原创 扫雷(1)

这里我打印棋盘是从1开始打印到9,完美绕过外围一圈的数据,而且后续不用调整x和y的值,因为现在玩家输入的坐标可以完美表示到数组中,数组下标为0的数据被完美避开了,现在可以把它看做数组下标从1开始的数组。先看第一步初始化,我这里选择了全部初始化为'0',布置雷就是布置'1'进去,这也是我选择用两个数组的原因,布置雷用'1',描述雷的数量也可能用到1,只用1个数组的话,无法分辨。这就是我们扫雷的棋盘了,打钩的地方就假设是雷的位置,我们需要设置这么一个棋盘,还要布置雷进去,然后给玩家显示出来就是上面的样子。

2023-02-17 22:09:44 234

原创 三子棋(井字棋)

所以我们在设计这个的时候需要注意到这个细节,在设定函数的时候,把棋盘数组中的坐标手动-1,就是真正的坐标了,判断语句就是正常加1不超棋盘。我们游戏的过程是怎么样的,我们来梳理一下,首先我们得要有棋盘,还得打印出来棋盘,然后玩家先开始下棋,下完一步我们给它打印出来,判断一下输赢,然后电脑下棋,打印出来,判断输赢。我把它分为三组 | | 和---|---|---|为一组,一共三组,而第三组是没有---|---|---的,我们就设置一个if语句,当循环到第三组的时候不打印---|---|---。

2023-02-15 21:06:31 216

原创 数据的存储(unsigned 以及char的截断和提升(原码,反码,补码))

就比如上面提到的1存入char类型变量,它的原码是00000001,这个就是截断,把32bit变成8bit,这个时候首个数字依旧是符号位,当他进行打印或使用的时候会还原成32bit,这个时候还原就是按照你的符号位去进行补充,这里是0,也就是补充为00000000000000000000000000000001。如图,我们按负数变成补码,这个时候这个补码就被当做了num的原码,num是无符号的,所以补码也是这个,所以最终打印出来的结果不是10。今天说的东西有点杂,咱们先讲最基础的原码,反码,补码。

2023-02-14 23:01:31 605

原创 strcpy函数的实现(内含assert和const见解)

这里要想返回值可以直接使用出来打印,我们需要注意的是:当你while循环完之后,*arr2所指向的地址已经是最后一位数了,如果这个时候你要返回arr2的话,就无法打印出来全部的arr2,这个时候只需要把一开始的arr2所指向的字符串首元素地址存储其来,到最后返回这个值,在代码中就是ret,然后printf就按照你这个首元素地址访问整个字符串。意思就是*score(解引用了这时候代表的是地址里存储的东西,在代码中是“hello”)不能改了,但是score(存储的是地址,在代码中是arr1)能改。

2023-02-14 13:19:36 758

原创 尼科彻斯定理(简单易懂)

这里我把1的单独列出来,会省事一点,直接把初始值设为1,当我输入2的时候进入第一个for循环,m=2减去2之后为0,符合条件进入循环,(0 + 1)*2 + 1,这里1就是第一次的初始值,加上1个奇数,3就是把2的过程先重复一遍,初始值为3,在加上。首先咱们可以观察到1到2之间的初始值是连续的奇数,2到3之间就隔了一个奇数,3到4之间就隔了两个奇数。可以知道这是一个递增的值,我们可以采用让每次的初始值加上n个奇数成为下一个数的初始值。简单易懂,2的立方就有两个奇数相加,3就有三个,4就有四个。

2023-02-02 18:51:04 2501

原创 数组(二维数组)

可以先按照这样子去理解它,它的行和列的下标同样都是从0开始的,像这样一组没什么特别的话就是按照顺序排下来,其余全补0。可以看到这串代码是用来求二维数组的每个数据的地址,观察可以发现,每个相邻的数组都是相差4,根据我们上篇文章。ok,把上次数组遗留下来的问题解决一半了,接下来是三字棋的小游戏了,可以期待一下,第一次做一个小游戏。再看看第二组,这里面多个括号{ },这里表达的意思是,括号里面的数字,为一行,如果不够就补齐0。可以看到,二维数组的创建就是比一维数组创建的时候多了一个[ ],分别表示它的行和列。

2023-01-21 19:06:57 192

原创 数组(一维数组)

这里的p是arr的首元素地址,它每次加1(整型,字节大小为4)后的地址,完美符合数组每个数据的地址,说明它们是等价的。再看看这个,前面两个正常都是加了4(这里怕有同学看不懂16进制,简单讲一下,16进制中c是12,12减去8为4),到了第三个的时候58到80,是28。第二个这里[]中是空的,那是不是错了呢,不是的,在你数组创建的时候是可以不写它的大小,这个时候它的大小就会默认为你{}中的数据个数,这里为4.再看看这个如果arr代表的是首元素的地址,这里应该打印的是4,为什么会打印出整个arr的大小呢。

2023-01-18 22:55:36 143

原创 函数(递归,迭代实现斐波那契数列)

在用户输入整数,这里举例输入1234,如何分解为一个个的数字,首先我想到的就是除10,由于int 只接收整形,所以每除一个10,就可以少一位。那么问题又来了,我除三个10可以获得1,除两个10的时候获得的是12,这时候要打印出去的话就是12了,如何打印2出来呢,这里我想到的是用求模,跟10求模。斐波那契数列(Fibonacci sequence), 斐波那契数列指的是这样一个数列: 1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584......

2023-01-17 16:46:52 2787

原创 函数(形参,实参)

所以说这里面具体的流程是这样的,Swap2(&a,&b),我们把a和b的地址传了进去,函数里面用指针(int* pa,int* pd)进行接收,接收到地址之后,进行解引用的操作*pa,*pb,这时候这两个值就是a和b的值了。上面我们说到,形参是实参的复制,是一块新开辟的空间,它们之间最大的隔阂就是地址不一样,无法影响到实参。说到这里,你是不是也想到了,c语言中对地址进行操作的,是不是指针以及解引用*,取地址符&。可以看到这个函数和上面那个函数的区别,(int* pa,int* pd),(&a,&b)。

2023-01-15 11:27:10 130

原创 辗转相除法

这里的运行过程是这样的,输入俩个数之后,这俩个数求余,不断赋值,不断求直到k = 0,循环不进入的时候,这时候n=最大公约数了。过程就是这样子,如果n>m也不影响因为18%24还是18,然后赋值一波就还是24%18了。上面这个代码是我当时想到的,笼统的说就是穷举法。到后面又学习到一个效率更高的方法:辗转相除法。昨天写了一个关于求两个数的最大公约数的代码。

2023-01-10 18:03:11 79

原创 折半查找(二分查找)

额外说一点因为我这里采用的是循环,left或者right会不断的改变,会出现到left大于right的,这个时候mid一样是可以找到的,这就是关于数学部分了,我就不多赘述了。第一种情况就是你查找的数字要大于mid的值,因为数组是有序的,所以你查找的值如果存在就一定在mid的右边,这个时候你原来的left的值就要发成改变了,变到mid的右边,也就是left = mid +1;可以看到一开始的right和left的状态是这样的,它们直接相加在一起就超出界限了,那么该如何找到它们的中间值呢。

2023-01-09 18:24:33 176

原创 缓冲区,getchar,[^\n]的理解

都是从输入缓冲区中读取的,并不是说从键盘输入中直接读取数据,具体流程是键盘输入的数据放到输入缓冲区中,然后getchar,scanf等输入函数从输入缓冲区里面读取数据。可以看到我们的运行结果正常了,用循环语句,判断getchar接收到的数据是否为\0,因为你最后一个数据肯定是\0,回车肯定是最后一个嘛。这里面输入密码的时候多了一个空格,而空格scanf不接收,这里面scanf只接收到了1234,剩下的都只能在输入缓冲区里待着,然后就被下面的getchar给接收到了。这样就可以实现这个代码的正确功能了。

2023-01-08 19:40:46 73

原创 链表的创建,打印,增,删

都说链表的创建需要开辟一块空间,那么这块空间到底是在哪里被开辟的?其实这块空间是在内存中的堆空间开辟。大概如图所示。大致了解一下就行。先了解一下什么是链表。我就直接讲一下物理结构,因为物理结构明白之后,逻辑结构一样会明白了。链表的一个空间里面会分为俩个部分,一个是数据域:专门用来存储数据的;一个是指针域:用来存储下一个节点的地址。它是如何连接的呢?其实就是靠这个指针域。除了尾结点之外,每个节点的指针域都会存储到下一个节点的地址。然后会通过这个地址来找到你所在的具体位置。

2022-12-19 20:17:46 297 2

原创 关键字static

一个普通的局部变量是放在栈区的,而被static的修饰的局部变量,是放在内存的静态区的存储位置发生了变化,使得局部变量出了作用域不会销毁,影响了变量的生命周期作用域不受影响。static修饰全局变量这时全局变量的外部链接属性就变成了内部链接属性,只能在自己所在的.c文件内部使用,其他.c文件无法使用。被static修饰的函数只能在自己所在的.c文件内使用,其他.c文件无法使用。这些就是我最近学到的有关关键字static的知识了,希望对你也有帮助。由此可见的效果是跟修饰全局变量是差不多的,都是无法使用了。

2022-12-10 20:43:47 82

原创 scanf函数实现多组输入

昨天复习到scanf函数的时候发现了自己对它的了解只停留在了用它实现接收输入这里,没有留意到其实scanf函数它本身存在一个返回值其类型是int,这让我有点惊喜,既然它存在返回值,那么我们就可以用它的返回值进行判断,能进行判断的话,自然就可以做为循环语句中的判断条件。用scanf函数作为判断语句我也是第一次使用,我就去尝试使用,看看scanf函数作为判断条件的时候到底是如何进行循环的。(后面了解到这其实是经典的多组输入的实现)

2022-12-06 10:17:23 1182 1

原创 我的编程学习

初学编程

2022-12-02 00:13:43 174 2

空空如也

空空如也

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

TA关注的人

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