- 博客(29)
- 收藏
- 关注
原创 网络编程套接字
直到处理完第一个连接请求。这样,只要取得某种sockaddr结构体的首地址,不需要直到具体是那种类型的sockaddr结构体,就可以根据地址类型字段确定结构体中的内容。我们已经知道,内存中的多字节数据相对于内存地址有大端和小端之分,磁盘文件中的多字节数据相对于文件中的便宜地址也有大端小端之分,网络数据流同样有大端小端之分,那么如何定义网络数据流的地址呢?之前学习系统编程的时候,知道pid是进程ID,表示系统中的唯一一个进程,此处的端口号同样也是表示一个进程,看起来两者非常相似,那么这两者之间是怎样的关系?
2023-07-18 01:43:19
227
原创 网络基础1
3.段和分组的转换,将传输层下来的较大数据段根据需要分割为更小的分组。因为网络协议采用分层的方式来进行设计和实现,上层不必关心底层的细节实现,只需要调用底层的接口以实现自身的功能即可。因为计算机的生产厂商有很多,操作系统也不少,网络硬件设备也很多,如何让这些不同厂商之间生产的计算机能够相互顺畅的通信,就需要有人站出来,约定一个共同的标准,让大家都来遵守,这就是网络协议。计算机之间的传输媒介是光信号和电信号,通过频率和强弱来表示0和1这样的信息,要想传递各种不同的信息,就需要约定好双方的数据格式。
2023-07-16 20:46:19
173
原创 Linux多线程
在一个程序里的一个执行路线就叫做线程(thread)。更准确的定义是:线程是一个进程内部的控制序列。一个进程至少都有一个执行线程。线程在进程内部运行,本质是在进程地址空间内运行。透过进程的虚拟地址空间,可以看到进程的大部分资源,将进程资源合理分配给每个执行流,就形成了线程执行流。在Linux系统中,线程(thread)是执行程序的基本单元。他是进程内的一个独立执行序列,与同一进程内的其他线程共享进程的资源,包括内存空间、文件描述符、打开的文件等。
2023-07-14 02:29:07
366
原创 Linux进程信号
当发生特定事件的时候,内核可以像进程发送信号,而进程可以捕获这些信号并执行相应的处理操作。sigismember是一个布尔函数,用于判断一个信号集的有效信号中是否包含某种信号,若包含则返回1,不包含则返回0,出错返回-1。在收到通知,再到你拿到快递期间,是有一个时间窗口的,在这段时间,你并没有拿到快递,但是你知道有一个快递已经到了,本质上是你记住了有一个快递要去取。当我们运行上述代码编译的可执行文件后,该进程会陷入死循环,知道我们向该前台进程输入 ctrl + c 终止该进程,他会发送出他捕获到的信号。
2023-07-12 00:12:30
93
原创 Linux进程间通信
进程间通信的主要目的是实现不同进程之间的数据交换和协作,以实现更复杂的任务和功能。以下是进程间通信的一些主要目的:数据共享:进程间通信可以用于共享数据,使得多个进程可以访问和修改相同的数据。这对于需要共享大量数据的任务非常有用,可以避免数据的复制和传输开销。资源共享:进程间通信可以用于共享系统资源,如文件、设备、数据库等。多个进程可以同时访问和操作这些资源,提高系统的并发性和效率。任务协作:进程间通信可以用于不同进程之间的协作和任务分配。
2023-07-11 20:21:29
166
原创 Linux基础I/O
下面这段代码用于在文件中写入数据首先使用fopen函数打开文件,如果没有该文件就创建一个同名文件。然后使用fwrite函数向该文件中写入数据。可以看到,创建了myfile这个文件,并且向其中成功写入了数据。下面的代码是用于读取文件中的数据并且成功向屏幕中成功打印了出来。ptr:指向要存储读取数据的内存位置的指针。size:每个元素的大小(以字节为单位)。nmemb:要读取的元素数量。stream:指向要读取数据的文件流。fwrite函数的返回值:如果成功读取了所有请求的元素数量,则返回值位
2023-07-11 03:04:20
91
原创 Linux进程控制
在Linux中fork函数是非常重要的函数,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。进程调用fork,当控制转移到内核中的fork代码后,内核会:1.创建一个新的进程控制块(PCB)来存储新进程的信息,包括进程ID、进程状态等2.复制父进程的内存空间,包括代码段、数据段、堆栈等,以创建一个与父进程完全相同的副本。3.在父进程和子进程中返回不同的值。在父进程中,fork函数返回子进程的进程ID;在子进程中,fork函数返回0。
2023-07-10 19:06:59
53
原创 Linux进程概念
子进程独立运行,并且可以执行不同的逻辑。指子进程在退出后,父进程没有及时回收子进程的资源,导致子进程的进程描述符等资源仍然存在,但是进程已经无法执行任何操作的一种状态。如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。它用于创建一个新的进程,新的进程是当前进程的子进程,当前进程是其父进程。
2023-07-10 02:26:36
50
原创 Linux基础开发工具
在Linux系统下安装软件,一个通常的办法是下载到程序的源代码,并进行编译,得到可执行程序。但是这样有些麻烦,于是有些人就把一些常用的软件提前编译好,做成软件包(可以理解成windows上的安装程序)放在一个服务器上,通过包管理器可以很方便的获取到这个编译好的软件包,直接进行安装。软件包和软件包管理器,就好比App和应用商店的关系。yum是Linux下非常常用的一种包管理器,主要应用在Fedora、RedHat、Centos等发行版上。需要注意的是:要想使用yum,需要保证主机(虚拟机)网络畅通。
2023-07-09 23:57:47
188
原创 Linux背景
说明:cp指令用于复制文件或目录,如同时指定两个以上的文件或目录,且最后的目的地是一个已经存在的目录,则它会把前面指定所有文件或目录复制到此目录中。tail命令从指定点开始将文件写到标准输出,使用tail命令的 -f 选项可以方便的查阅正在改变的日志文件,tail -f filename 会把filename里最尾部的内容显示在屏幕上,并且不断刷新,使你看到最新的文件内容。索引节点存储了文件的元数据,包括文件的权限,所有者,大小,时间戳等信息,以及指向文件数据块的指针。他是基于当前位置的相对位置表示。
2023-07-09 23:52:39
73
1
原创 C++初阶到进阶
C++是在C的基础之上,容纳进去了面向对象编程的思想,并增加了许多有用的库,以及编程范式的一门通用的高级语言,广泛应用于编写系统软件、游戏引擎、图形界面应用程序和其他性能要求较高的软件系统。C++是C语言的扩展,具备了C语言的底层编程能力和高级语言特性。以下是C++的一些特点和优势:面向对象:C++支持面向对象编程范式,可以使用类、对象、继承、多态等特性来组织和管理代码,提高代码的可重用性和可维护性。
2023-07-07 00:33:20
1135
1
原创 leetcode每日一题系列
由此我们可以想到用递归遍历的方式解决,每一次递归的时候,与当前节点进行比较,如果是递归左子树,就将本节点作为最大值;递归右子树,就将本节点作为最小值。题目分析可知,这是对二叉搜索树性质的一个考察。二叉搜索树在拥有二叉树性质的同时,还具有普通二叉树不具有的性质,即左节点 < 根节点 < 右节点。,判断其是否是一个有效的二叉搜索树。给你一个二叉树的根节点。
2023-06-27 23:40:35
373
1
原创 23.6.26刷题
题目分析可知这是一道中序遍历的变种题目,是对二叉搜索树的中序遍历。因为题目要求我们找到二叉搜索树中第k小的元素,不难想到,需要构建这个二叉树的有序序列以方便的找到第k小的元素。由于二叉搜索树的性质,即左节点 < 根节点 < 右节点。因为中序遍历是先访问左节点,在访问根节点,最后访问右节点。题目要求我们找到二叉搜索树中的最小绝对差,不难想到我们可以设置一个全局的绝对差,并且在遍历的过程中,事实更新这个全局的绝对差。差值是一个正数,其数值等于两值之差的绝对值。给你一个二叉搜索树的根节点。
2023-06-26 23:25:13
73
1
原创 C++中class和struct的相关知识
class和struct都可以用来定义成员变量和成员函数,并且可以包含公有,私有,和保护成员。class的默认继承方式为私有继承,即派生类继承基类的成员时,默认继承方式为私有继承。私有继承即派生类的对象中有基类的成员,但是派生类没有对其的访问权限。class的默认访问权限是私有,即在类内定义的成员默认为是私有成员,如果不用访问限定符修饰的话。struct的默认访问权限是公有,记载结构体内定义的成员默认为是公有成员,不论是类内还是类外都可以直接访问。而struct的默认继承方式为公有继承。
2023-06-26 18:56:51
493
1
原创 每日一题之leetcode103:二叉树的锯齿形层序遍历
由此就可以简单的想到,需要使用队列来实现层序遍历,使用二级数组来存储每层的元素。要想实现每一层调换一次方向,可以使用一个布尔值来控制遍历的方向,每一层遍历结束将其取反,就可以简单的实现每一层调换一次方向。题目要求我们每一层遍历的时候,调换一次方向,并且将调换方向后的每层元素保存起来。level[size-1-i] = node.Val // 从右到左添加节点值到当前层。//标志位,表示当前层的遍历方向。isLeftToRight := true // 标志位,表示当前层的遍历方向。
2023-06-25 23:33:21
54
原创 C++基础中引用和指针
空指针并没有危害,而野指针不同,野指针潜在的危害非常巨大,再代码中一定要避免出现野指针。因为野指针是指向一块无效的地址的指针,他对这块内存拥有访问权限,但是开发者并不清楚其具体的指向。引用:引用是用于将一个已存在的变量取一个别名,这个别名即为已存在变量的引用。也就是说,原始变量和引用所占用的内存空间是一样的,只是引用和原始变量两个名字不同罢了。指针可以进行空指针的判断,即指向空地址的指针。并且不能改变绑定关系,也就是说,引用了a变量后,这个变量不能再成为b的引用,只能作为a的引用存在。
2023-06-25 19:32:44
56
原创 C++基础之变量和数据类型
是因为long类型在不同的系统中所占的字节数是不一样的,其在32位系统中所占字节为4,在64位系统中所占字节为8。指针:用于存储变量的地址,也就是说指针是一个变量,但是这个变量的值是其所指向的变量的地址。新手对于指针可能会非常困惑,主要是指针涉及到两个地址,一个是指针本身的地址,另一个是指针所指向的变量的地址,这两个地址是不同的概念。其中,StructName是结构体的名称, DataType1 、DataType2 是结构体成员的数据类型,member1、member2 是结构体成员名称。
2023-06-25 13:27:28
210
原创 每日一题之leetcode637. 二叉树的层平均值
有题目分析可知,这是二叉树层序遍历的一个变体。主要思路就是在每一层遍历的时候,计算每层的平均值。// averageOfLevels 获取每一层节点的平均值。// 将当前节点的左右子节点加入队列。, 以数组的形式返回每一层节点的平均值。//将当前节点的左右子节点加入队列。// 遍历当前层的节点,计算节点值的和。// 计算当前层的平均值并加入结果数组。//遍历当前层的节点,计算节点值的和。//计算当前层的平均值并加入结果数组。// 更新队列,继续处理下一层节点。// TreeNode 二叉树节点的定义。
2023-06-24 19:17:10
111
1
原创 每日一题值leetcode199. 二叉树的右视图
其解题思路就是在每一层遍历的时候,再做一次小的遍历,直到这层的末尾,然后再将这个末尾节点,也就是这层的最右边节点保存起来。,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。// 遍历当前层的节点,将最右侧的节点值加入结果数组。//遍历当前层的节点,将最右侧的节点值加入结果数组。// rightSideView 获取从右侧所能看到的节点值。// 将当前节点的左右子节点加入队列。//将当前节点的左右子节点加入队列。// 将当前节点的值加入结果数组。//将当前节点的值加入结果数组。
2023-06-24 19:11:00
46
1
原创 每日一题之leetcode236. 二叉树的最近公共祖先
中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(//如果只在左子树中找到了最近公共祖先,则返回在左子树中的最近公共祖先。//如果只在右子树中找到了最近公共祖先,则返回在右子树中的最近公共祖先。// 如果只在左子树中找到了最近公共祖先,则返回左子树中的最近公共祖先。// 如果只在右子树中找到了最近公共祖先,则返回右子树中的最近公共祖先。// 在左子树中查找p和q的最近公共祖先。自然就可以想到是递归遍历的思路。
2023-06-24 18:48:28
57
1
原创 每日一题之leetcode222. 完全二叉树的节点个数
二叉树的层序遍历,一般采用队列来实现,由于队列的先入先出特性,可以很好的支持层序遍历。每一次访问节点时,既要做题目要求的操作,还需要将其子节点入队,等待下一层的遍历。的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。以下是go语言的代码,由于go语言没有c++的std标准库,也就没有成熟的队列容器可以使用,所以采用slice切片来模拟c++中的队列。return 0 //如果根节点为空,则节点个数为0。
2023-06-24 17:52:51
44
1
原创 每日一题之leetcode173. 二叉搜索树迭代器
it.nodes = it.nodes[:len(it.nodes)-1] // 切片缩小,弹出末尾的节点。return len(it.nodes) > 0 // 检查切片是否为空,判断是否还有下一个元素。it.pushAllLeft(node.Right) // 将右子树的左子节点依次入栈。node := it.nodes[len(it.nodes)-1] // 取出切片末尾的节点。it.pushAllLeft(root) // 将根节点及其左子节点入栈。//将当前节点及其左子节点依次入栈。
2023-06-24 15:06:25
63
1
原创 每日一题之leetcode124. 二叉树中的最大路径和
分析题意可知,这道题目也是中序遍历的一道变体,也就是需要递归的访问根左右,然后计算每一个路径上的最大路径和;此外还需要有一个全局的最大路径和,每一个路劲计算出的最大路径和都要和全局的最大路径和进行比较,哪个和大,全局最大路径和就更新为哪个和。以下是go语言的完整代码,由于go语言没有c++中内置的max函数,需要我们自己手动实现一个。//返回当前节点作为路径一部分的最大路径和。//计算当前节点作为路径起点的最大路径和。//递归计算左子树和右子树的最大路径和。//计算当前节点作为路径和的最大路径和。
2023-06-24 14:46:07
343
1
原创 每日一题之leetcode129. 求根节点到叶节点数字之和
由题意分析可知,其主要考察的是二叉树的中序遍历,也即根左右。因为题目规定,每一层的二叉树节点的数量级是不同的,随着层数的增加,第一次的数量级大小也随之增加。只有中序遍历可以独立的遍历二叉树的每一个路径,才能顺利的得出每一个路径的数字之和。//递归计算左子树和右子树的数字之和,并累加到当前路径的数字之和。//递归计算左子树和右子树的数字之和,并且累加到当前路径。//如果当前节点是叶子节点,则返回当前路径的数字之和。//如果是叶子节点,则返回当前路径的数字之和。两种语言的思路一致。//计算当前路径的数字之和。
2023-06-24 13:53:39
276
1
原创 每日一题之leetcode112.路经总和
是因为二叉树的性质之一就是根节点的左子树和右子树同样也是一个二叉树,由此就可以将目标和减去根节点的值,成为一个新的目标和,用以判断子树中是否有正确的目标路径。//如果当前节点为叶子节点,并且节点值等于目标和,则存在路径。//如果当前节点为叶子节点且节点值等于目标和,则存在路径。的路径,这条路径上所有节点值相加等于目标和。下面为go语言的代码,两种语言的解题思路一致。//递归判断左子树和右子树是否存在路径。//如果根节点为空,则不存在路径。//如果根节点为空,则不存在路径。是指没有子节点的节点。
2023-06-24 13:27:40
51
1
原创 每日一题之leetcode114
一是需要以前序遍历的方式来遍历二叉树,二是在遍历的过程中将原有的左子树挂到右子树的位置上形成新的右子树,随后将旧的右子树挂在新的右子树即之前的左子树之后。其中首先要保存原有的左右节点,避免在左子树替代右子树时,丢失原有的数据,然后遍历新的右子树,直至末尾,再将保留的右子树挂到新的右子树上即可。其中前序遍历必要容易解决,主要的解法为递归,首先访问根节点,然后递归左子树,最后递归右子树。然后是如何解决第二个难题,也就是如何将左子树成为新的右子树,右子树挂到新的左子树上。//将原来的右子树连接到新右子树的末尾。
2023-06-22 23:00:54
41
1
原创 23.6.20每日一题
这时候我们就可以想到一个非常经典的解决二叉树的层序遍历的方法,即使用队列来进行层序遍历。在这个层序遍历的过程中,对二叉树的节点进行操作,大致就是这类考察层序遍历的题目的变形所在。由于go语言没有c++中的std标准库,也就没有方便的队列容器使用,但是可以使用slice切片来模拟队列,使用append进行入队操作。回到这道题目,让我们将每一个节点的next指针,指向他的右兄弟,若没有,指向空。就可以在这层序遍历的过程中,改变next的指针的方向。简单分析可知,这道题目是考察二叉树的层序遍历的。
2023-06-20 23:28:46
34
原创 力扣106:从中序与后序遍历序列构造二叉树
二叉树的后序遍历中,首先递归的遍历左子树,然后递归的遍历右子树,最后再访问根节点。其具体的遍历过程是:1.首先检查当前节点是否为空,若为空,结束遍历,不为空继续遍历。二叉树的中序遍历是,首先递归的访问左子树,然后递归的遍历右子树。二叉树的前序遍历是,先访问根节点,然后递归的遍历左子树,最后在递归的遍历右子树。其具体的遍历过程是:1.首先检查当前节点是否为空,若为空,结束遍历,不为空继续遍历。由此,可以唯一的确定一个二叉树,因为在二叉树中,根节点的位置和左子树、右子树的结构共同决定了二叉树的形状。
2023-06-20 01:20:07
127
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人