- 博客(37)
- 收藏
- 关注
原创 让天底下没有难学的链表1
上篇文章,我们详细地逐字逐句的讲解了顺序表的创建及其使用。想必大家对于顺序表使用的一个内部思路都已经非常清楚了,但是我们也讲过,顺序表存在一些不足这里再给大家贴一下。1. 中间/头部的插入删除,时间复杂度为O(N)2. 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。3. 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。那么今天我们就正式进入正题:链表。
2025-03-11 15:42:26
543
原创 小白也爱看的数据结构(顺序表完结)
时间紧,任务重。我们直接开始。我看了一下上一篇文章的具体的讲解,需要上下翻看很不容易,这篇文章,我就会以注释的形式写在代码里,必要的细节再给大家讲解。当然相比于前面的代码,现在的一各个函数就是洒洒水啦。
2025-03-09 16:15:35
208
原创 小白也爱看的数据结构(顺序表)
本文的顺序表和链表两者异曲同工,读者在阅读学习的时候可以自己亲身体会一下两者各有什么差距,可能有读者会说,在后续c++的库里面都可以直接用,只要大致了解,但是,实际上,没有数据结构的了解,我们很难真正意义上将这个函数或者代码运用到极致。看到这,你可以狭隘地理解为,差距就是体现在动态数组的创建上,从而引发的一些访问与输出的问题,当然根据我们所知的知识,肯定也会影响我们的时间复杂度和空间复杂度。下面是标准版的顺序表的格式,这里的格式就会显得非常的呆板。但是基本的插入又分为头插和尾插,删除也分为头删和尾删。
2025-03-09 15:45:27
822
原创 小白也爱看的初阶数据结构1
好了,从今天开始我们就正式进入到了初阶数据结构的范畴,在此之前我还是先跟大家说一下前言,了解一下数据结构。大家在学习的时候才能更加有动力和激情。
2025-03-08 17:24:57
818
原创 那些不为人知的文件操作知识2
朋友们,承接上文。我上篇文章发布出去的时候想到缓冲区的内容忘记讲了,不过没关系,放在这一篇文章里面更加能体现内存空间的变化。缓冲文件系统文件缓冲区文件在读写之前应该先打开文件,在使用结束之后应该关闭文件。ANSIC 规定使用fopen函数来打开文件,fclose来关闭文件。具体的方式如下,这个就像我们在使用printf的时候所标注的%d这种是一样的意义。这个代码比较简单,不做过多解释,可以放在ai里面自己去尝试理解,主要要理解这个逻辑。上面是c++的网站,这里解释一下什么是输入输出流。
2025-03-07 22:13:50
969
原创 那些不为人知的文件操作知识1
好了朋友们,这将是我们在c语言知识的最后一节课,正如题目所言,关于文件的各种知识,你可能或多或少的听过,但一定没有系统性的学习过,比如文件的后缀.c文件和txt文件为什么是这样,好,今天这篇文章我们就来深入的讲解。如有整数10000,如果以ASCII码的形式输出到磁盘,则磁盘中占用5个字节(每个字符一个字节),而二进制形式输出,则在磁盘上只占4个字节(VS2013测试)。文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容的文件。这里我们讨论的是数据文件。
2025-03-07 21:17:49
1080
原创 非常重要的动态内存错误和柔性数组2
在 free(str) 之后,str 指向的内存已经被释放,但后续代码仍然尝试使用 str(如 strcpy 和 printf),这会导致未定义行为。这里很明显就能看到,这里引用的函数名是不匹配的。然后这里printf的打印是不标准的,有些编译器可能会让你通过,当然有些就已经报错了,程序不稳定,有安全风险。但是被static修饰的变量存放在数据段(静态区),数据段的特点是在上面创建的变量,直到程序结束才销毁。实际上普通的局部变量是在栈区分配空间的,栈区的特点是在上面创建的变量出了作用域就销毁。
2025-03-06 20:00:36
1110
原创 非常重要的动态内存错误和柔性数组1
因此,GetMemory 返回的指针指向一个无效的内存区域,导致 Test 函数中的 printf 操作会引发未定义行为(表现通常是打印乱码或程序崩溃)。承接上次的动态内存的分享,我想想还是把具体的易错点分享一下,再跟大家分享四道非常经典的笔试题,以后找工作会发现,很多题就是这四道题的原型。这个后面两篇文章会讲。在 Test 函数中,str 被初始化为 NULL,但通过 GetMemory 赋值后,它指向了一个无效的内存地址。程序分配了内存但没有释放,导致内存被持续占用,最终可能导致系统内存耗尽。
2025-03-06 19:34:08
651
原创 小白也能看懂的深度学习7
还是用原本视频的例子最为贴近来解释关于广播的矩阵算法。这是一个不同食物(每 100g)中不同营养成分的卡路里含量表格,表格为 3 行 4 列,列表示不同的食物种类,从左至右依次为苹果,牛肉,鸡蛋,土豆。行表示不同的营养成分,从上到下依次为碳水化合物,蛋白质,脂肪。那么,我们现在想要计算不同食物中不同营养成分中的卡路里百分比。 现在计算苹果中的碳水化合物卡路里百分比含量,首先计算苹果(100g)中三种营养成分卡路里总和 56+1.2+1.8 = 59,然后用 56/59 = 94.9%算出结果。 可以看出苹果
2025-03-04 16:24:25
946
原创 小白也能看懂的深度学习6
它的假设函数是sigmoid函数,也就是hθ(x) = 1/(1 + e(-θT x)),这里的θ是参数向量,x是特征向量。如果是非向量化的方式,也就是逐个样本计算的话,梯度下降的更新规则可能是这样的:对于每个θ_j,计算梯度项,然后累加所有样本的梯度,再取平均,然后乘以学习率α,最后用这个来更新θ_j。比如,对于所有样本,梯度的计算可以表示为X的转置乘以(h - y)然后除以m,也就是 (1/m) * X^T (h - y),其中h是sigmoid(Xθ)的结果。这里的求和是对所有样本i=1到m进行的。
2025-03-04 15:44:06
323
原创 小白也能看懂的深度学习5
从这幅图中也不难见得我们的意图,本质上,我们就是将一连串的数据变成了一些行向量和列向量,再通过矩阵化的乘法,从而对一组数据进行计算训练,比显性的for循环快速很多。前向传播是训练和推理过程中必不可少的步骤。它可以让 python 的充分利用并行化计算,这是事实在 GPU 和 CPU 上面计算,GPU 更加擅长 SIMD 计算,但是 CPU 事实上也不是太差,可能没有 GPU 那么擅长吧。现”,但是我做的所有的案例都是在 jupyter notebook 上面实现,这里只有 CPU,CPU 和 GPU。
2025-03-03 18:00:42
752
原创 小白也能学会的深度学习4
我们上面刚讲了,我们要让损失函数尽可能的小,或者说,我们要让损失函数算出来的值尽可能的靠近实际值,而且还要把我们的成本降到最低,在这里面,训练集的选择就变得至关重要了。值得一提的是损失函数是在单个训练样本中定义的,它衡量的是算法在单个训练样本中表现如何,为了衡量算法在全部训练样本上的表现如何,我们需要定义一个算法的代价函数,算法的代价函数是对m个样本的损失函数求和然后除以m,这就是一个非常明确的目的。大家好,上篇文章我们讲了逻辑回归的模型,也知道逻辑回归的成本是很高的,我们需要去 不断的优化再优化。
2025-03-03 17:16:52
264
原创 一看就懂的动态内存管理1
这时候就只能试试动态内存开辟了。什么意思呢,就是我们系统开辟内存的时候分为三个区域,一个是栈区一个是堆区,而我们的动态内存就是在堆区上开辟的,包括图里面的四个动态内存函数也都是在堆区上用的。malloc 是 "memory allocation" 的缩写,用于在堆上分配指定大小的内存块,并返回指向该内存块的指针。好这篇文章我们就来看看动态内存的管理,这篇文章的知识就涉及到栈帧的的创建和数据结构方面的知识了,换句话说,也是在。如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
2025-03-02 14:13:52
371
原创 看完就进阶的结构体完结篇4枚举和联合
联合也是一种特殊的自定义类型 这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以联合也叫共用体)。//联合类型的声明union Unchar c;int i;//联合变量的定义//计算连个变量的大小。
2025-03-01 19:53:25
693
原创 看完就进阶的结构体完结篇3位段
承接上文,讲完了结构体我们就得来讲讲位段。位段(Bit Field)已经涉及是C/C++语言中的一种数据结构,它允许你在结构体或联合体中定义特定宽度的字段。位段的主要用途是节省内存空间,特别是在嵌入式系统或对内存使用有严格限制的应用中。什么是位段位段的声明和结构是类似的,有两个不同:1.位段的成员必须是 int、unsigned int 或signed int。2.位段的成员名后边有一个冒号和一个数字。在这里A就是一个位段类型那位段A的大小是多少?怎么计算呢?
2025-03-01 19:19:43
1098
原创 看完就进阶的自定义2
有了结构体类型,那如何定义变量,其实很简单int x;int y;}p1;//声明类型的同时定义变量p1//定义结构体变量p2可以直接在花括号后面跟定义,也可以单独定义。那初始化呢?//初始化:定义变量的同时赋初值。struct Stu //类型声明//名字int age;//年龄//初始化直接赋值初始化。或者嵌套初始化int data;//结构体嵌套初始化//结构体嵌套初始化结构体内存对齐我们已经掌握了结构体的基本使用了。现在我们深入讨论一个问题:计算结构体的大小。
2025-02-26 20:06:46
486
1
原创 自定义类型看完这篇就进阶1
这篇文章我们来讲讲所谓的自定义类型。自定义类型:结构体,枚举,联合首先我们先来看结构体。可以说,结构体这块知识你学通透了,后面的枚举和联合将不攻自破了。
2025-02-26 19:29:02
837
1
原创 小白也能学会的深度学习3
我们用w来表示逻辑回归的参数,这也是一个维向量(因为w实际上是特征权重,维度与特征向量相同),参数里面还有b,这是一个实数(表示偏差)。对于二元分类问题来讲,给定一个输入特征向量x,它可能对应一张图片,你想识别这 张图片识别看它是否是一只猫或者不是一只猫的图片,你想要一个算法能够输出预测,你只能称之为y^,也就是你y的估计。例如有一个包含x个样本的训练集,你很可能习惯于用一个 for 循环来遍历训练集中的每个样本,但是当实现一个神经网络的时候,我们通常不直接使用 for 循环来遍历整个训练集。
2025-02-24 16:09:55
373
1
原创 小白也能看懂的深度学习2
可以知道的一个使用 sigmoid 函数和机器学习问题是,在这个区域,也就是这个 sigmoid 函数的梯度会接近零,所以学习的速度会变得非常缓慢,因为当你实现梯度下降以及梯度接近零的时候,参数会更新的很慢,所以学习的速率也会变的很慢,而通过改变这个被叫做激活函数的东西,神经网络换用这一个函数,叫做 ReLU 的函数(修正线性单元),ReLU 它的梯度对于所有输入的负值都是零,因此梯度更加不会趋向逐渐减少到零。有些人会说,音频这些东西,我们人类是很容易使用的,或者说,最先开始使用的就是非结构化数据。
2025-02-24 15:31:08
990
原创 字符函数和字符串函数3完结篇
上一篇文章讲了长度受限制的字符串函数介绍strncpystrncatstrncmp以及字符串查找的两个函数strstrstrtok今天这篇这个文章就是这个系列的完结了,接下去的是动态内存管理和结构体的内容,后面就转到用c语言的初阶数据结构了。
2025-02-22 14:53:10
1042
原创 字符函数和字符串函数2
接续上文,我们讲了求字符串长度的strlen还有长度不受限制的字符串函数strcpystrcatstrcmp那么本篇我们就继续来讲长度受限制的字符串函数。
2025-02-22 07:00:00
783
原创 字符函数和字符串函数1
C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在 常量字符串中或者字符数组里字符串常量适用于那些对它不做修改的字符串函数.
2025-02-21 12:28:47
792
原创 小白也能看懂的深度学习 第一门课1
我们知道深度学习是指训练神经网络的过程。但是有时它指的是特别大规模的神经网络训练。这里就举了一个例子。我们想探讨房子大小和房价的关系。那么我们就要有一个计算的公式,但是在这之前,我们得知道这个公式是怎么形成的,也就是拟合函数。如果是直线,那就是一个一次函数。那就会出现下面这张图。这就是高中学的线性回归,也就是经验回归,通过我的样本数去看,什么因素大概影响我的房价,最终确定下来这个值,那就形成了一个固定的函数了。
2025-02-21 07:00:00
335
原创 细到极致的操作符(3)
代码二此处if (a =b + 1, c=a / 2, d > 0)代码是错误的,代码中`d`未定义,不过仅从已有正确部分看,先执行`a =b + 1`(此时`a`被赋值为`2 + 1 = 3`),然后执行c=a / 2(`c`被赋值为`3 / 2 = 1`,因为是整型除法),但由于`d`未定义所以是无法判断整体`if`条件是否成立的。逗号表达式,就是用逗号隔开的多个表达式。先计算`a>b`,此时`a = 1`,`b = 2`,`a>b`为假(值为0),但这个结果在逗号表达式中会被丢弃。
2025-02-20 07:00:00
778
原创 细到极致的操作符(4)必看篇
如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类型,否则操作就无法进行。如果我们写出的表达式如果不能通过操作符的属性确定唯一的计算路径,那这个表达式就是存在问题的。这里列一下这个东西,如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算。表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度。因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长。
2025-02-20 07:00:00
1231
原创 细到极致的操作符(2)
这里要注意的是sizeof后面必须要加上括号,不然就会出错。赋值操作符是一个很棒的操作符,他可以让你得到一个你之前不满意的值。这里自己去运行一下就会发现,sizeof返回的是整个数组的大小,也就是整个数组的字节数。当然这里要提一下,赋值操作符是可以连续使用的。这些关系运算符比较简单,没什么可讲的,但是我们要注意一些运算符使用时候的陷阱。知道复合使用的逻辑和知道原来这个是可以复合的就基本差不多了。警告: 在编程的过程中== 和=不小心写错,导致的错误。-- 前置、后置--
2025-02-19 17:58:44
249
原创 细到极致的操作符知识点(1)
虽然很难理解,但是我还是放出来,你只需要知道的是这会极大的方便程序员的位级别的运算,同时也可以进行快速乘除。想了很久还是想分享一下c语言里面的操作符,这篇文章的操作符和其他不一样,就像标题所说,细到极致,别人没有的这里都有!这个移位操作主要是对于二进制的整数进行的一个,平常一般不会用,一般都在按位异或或者计算2的高次幂的时候能更加高效。想不到是正常的,学的越多越想不到,所以每一个部分基础都要打好,这可是一道面试题,想想有多变态吧,难倒一片。如果你是挣扎着做出的,那恭喜你,你一定印象很深刻了。
2025-02-19 17:30:33
378
原创 函数看完这篇就登峰造极第四部分,迭代
首先,在这里放一个递归的自定义函数,这里解释一下,谁的阶乘就是,从1一直加一到你这个数的所有数的乘积。那么也就意味着你这个数一定是多变的,如果你的n取到了很大的数,那很麻烦。等于第三项就单独拎出来算了两遍,但是以此类推,如果这个n很大的时候,比如50,就会具有一个特别大的计算量,程序运行的时间就会变得很长。这里给大家贴一个代码,大家直接复制粘贴去运行一下就会发现,这是千万级的计算量,就50为例的时候,但是50肯定不能满足我们,这就说明这个代码的效率实在是太低了。这就涉及到了函数栈帧的创建了,这里是栈溢出。
2025-01-15 22:11:06
584
原创 函数看完这篇就登峰造极第三部分 3/4
噢,这样一想还真的是,我在输入的时候已经不能用int了,得用什么呢?再者,打印他的每一位,数位分离这是我们的基本功,但是我们所得到的数据是4321,如果简单的把这些数据存储起来再逆序输出,可又会涉及到这个数的位数问题是未知的,不好搞定。但是常规的想法就是按位输出,如何再拿到4321,最后1234就可以了,按位输出可以用一个for循环加while循环去实现,当数/10=0的时候为假就可以了,然后灵光一现,我可以用一维数组去存储这些数字啊,最后按照下标逆序输出不就好了。,那具体是什么意思呢,用一个代码讲透。
2025-01-13 21:21:31
258
原创 函数看完这篇就登峰造极第二部分 必看
讲到这里再插一嘴,我们讲局部变量和全局变量哪个好,肯定是局部变量好,但是相对的难度更大,对于作用域要十分清晰,所以很多人写代码啪一下把全局变量写在那就过了,但是对于团队的项目呢,你的全局变量,一旦代码一改,或者名称有重复呢,当然更深层的还是函数栈帧模块,全局变量的空间的占用,简单一说,就是你的全局变量可能会占用空间从而影响到别人的代码。这里的.h代表的是我们编译器里面的头文件,.c文件则代表我们的源文件,也就是说当我们写好一个函数的时候,直接像代码中所显示的那样引用一下就好了。不然会出现临时卡壳的情况。
2025-01-13 18:13:08
594
原创 函数重点看完这篇就登峰造极第一部分
在main函数中传给Swap1的num1, num2和传给Swap2函数的&num1,&num2是实际参数。所以我们的自定义函数,或者是cpp网站的函数后面的参数都用的是地址,这就是传址调用。类似于我们要改合同,改了复印件不改原件,但是实际上,具有法律效益的还得是我们的原件,复印件只是一种拷贝。
2025-01-12 22:09:41
511
原创 不一样的函数要点(从小白开始精通)
也就是说,我这就相当于九九乘法表,需要用到的时候能脱口而出,这样就可以避免我们去再一次次用小学老师教的方法去列竖式,但是弊端也很容易就显现了,如果给你一个9*9你马上就知道是81,但是我要是给你的9.1*9.1呢,(这里的例子可能不太恰当,因为标点是格外加上就好了)但是在编程里,我们要实现这样的乘法,单一的库函数肯定是不能兼容运行了,所以这个时候就要用自定义函数。这篇文章,我将讲解几个在日常使用中不容易注意到的要点,函数我们所要学习的远不止自定义函数,库函数,不单单就是为了解题,ok话不多说开始。
2025-01-12 21:36:37
312
原创 实用技巧续篇
这里对于新人不是很友好,但是没关系,你把前面一串的字符记成门牌号就行了,就像我们平常很容易就出现的访问越界的问题,如果我知道了你的地址,也知道了目的地的地址,是不是就知道往哪走了?这里确定调试开始以后,我们找到调试窗口里面的监视,就会出现图片里面的这个图片,在里面输入自己定义的名称,如何呢,然后继续按F10,逐步走下去,同时观察右边的数值的变化就可以了。这里可以看我们在使用的寄存器的具体信息,也就是之前提到的esp,ebp那些,大致有个了解就行。初学者可能80%的时间在写代码,20%的时间在调试。
2025-01-11 20:21:34
252
原创 VS2022实用调试技巧(从小白开始学习)
总的来说,Debug的版本,更能让我们看到每一步计算机是怎么走的,所以我们说调试就是在Debug版本的环境中,找代码中潜伏的问题的一个过程。上图的ebp,esp等都是寄存器,所以Debug和Release本质上的区别就是开辟内存的顺序不一样所导致的程序执行的结果也不一样。这是人类历史上第一个错误,在当时,人们对于第一次出现的错误,从头开始算了很久,后面一想,要是以后又出现错误,每次都要一次次重推,这不是麻烦死了,于是就想,能不能设置观察运行的自检程序,减少推导呢,于是,调试,应运而生。
2025-01-11 19:48:40
386
原创 总结编程思想的引用与迁移的认知误区
我今天在学习指针的时候,了解到指针的解引用和二级指针,我不禁想到了一维数组和二维组,于是突发奇想下,能不能用一维数组去模拟二维数组的实现呢?利用四个一维数组就可以实现二维数组的转变,但是看到这里,读者朋友们一定会对我唏嘘不已,认为我浪费了你们的时间,但别担心,请接着看下去,保证我的感悟会对你有所帮助。而是迁移原因与程序设计中的底层思想,凡是设计程序必是由繁琐到简单,而所谓的二级指针那些也是在变得简单的时候设计出来的。我们在反复从一级到二级的过程中探究程序的可能,但是假如用参量,是不是就会更生搬硬套呢?
2024-08-30 18:36:02
365
oj上题目的讲解,这里给大家总结了一下四大排序基本语法框架
2024-11-11
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人