自定义博客皮肤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)
  • 收藏
  • 关注

原创 网络基础(1)

我们都知道计算机是只认识0和1的,但是不同的机器对于这种0和1信息的识别也是不一样的,例如有的设备对于0和1信息的识别靠的是电流的频率,而有的设备对于0和1信息的识别靠的是电流的强弱,也就是每种品牌的电脑,内部是被0和1信息都是被供应商做好规定了的。磁盘的供应商有自己的协议,网卡有自己的协议。两个人在打电话,逻辑上两个人是直接在通电话,但是物理上我的声音是被我的电话接收,然后我的电话经过种种的处理,然后将处理过的信息传递给对面的电话机,对面的电话机在对接收的信息进行处理,才让两个人实现了电话的通信。

2024-04-06 15:03:04 1047

原创 简单线程池的实现

这样写有几个好处,当有好几个线程检测到这里的_instance为nullptr时,会都进入到第一个if中,然后在这里获取锁,而只有一个线程能够得到锁,然后去到第二个if中创建单例对象,之后这个线程会释放锁,其它线程获取到锁之后,此时_instance已经不是nullptr了自然就不会继续创建单例对象了。对于这个下限和上限的具体的数量,是根据业务情况而定的,这里就可以写一个配置文件,在配置文件中写明低水位线为多少,高水位线为多少,然后在构造函数中读取这个文件,将低水位线和高水位线的值获取到即可。

2024-03-29 15:04:00 708

原创 线程的互斥,生产消费者模型

在之前的学习种我们知道了在,多线程的情况下,对一个全局变量做++,并不是原子的。并且在之前的学习中,我们学习到了给临界区加锁,在之前的代码中我们使用的是一个全局的锁。并且为了保证锁能够保护临界区,所以这里首先就要保证申请锁是一个安全的行为。至于原理之后会说明。如果你定义的是一个局部的锁,要对锁进行初始化需要使用下面到的函数。依旧使用destroy来销毁锁。下面我们来修改一下我们上面写的代码,让其变成一个使用局部锁的代码。代码如下:首先我们就要创建出一个局部的锁。然后修改我们之前封装的线程库,将这个锁作为参数

2024-03-19 12:54:33 817

原创 c++单例模式

后面启动的进程都是由前面的进程带起来的,就以bash为例子,创建的bash就可以说是最早的进程了,你将bash关闭了,很多的进程也就没有了。需要注意的就是这里的_inct是不存在于这个类对象中的,这里要将其放到类中是因为c++讲究的就是一个封装,封装的意思也就是管控,也就是要将这个_inst管控起来(收到访问限定符的限制)可以访问家人(private修饰的成员)。现在我们写的这个单例模式所对应的类,内部所包含的成员是很少的,但是在一个项目中,一个单例模式的类中所包含的成员一般是比现在的这个多的,

2024-03-04 07:41:30 1084 1

原创 System V版本的共享内存

在之前的学习中我们学习到了使用匿名和命名管道进行进程间的通信,下面我们再来使用一种新的方式进行进程间的通信。我们下面要学习的是system V版本的共享内存。首先我们要知道什么是system V首先我们要知道我们在之前学习的管道通信的代码并不是一个专门设计出来的模块,我们之前所学习的管道通信是复用了文件系统模块的代码的。但是我们在实际的使用场景上来说,只有一种通信方式是不够的。所以我们还是需要有其它的通信方式存在。由此就有人设计了一个专门用于进程通信的模块。

2024-02-27 07:00:00 1564

原创 管道通信(下)命名管道和简单日志函数的制作

在一个比较完善的服务运行过程中,肯定是会出现一些问题的,这些问题根据严重的程度不同我们的做法也是不一样的。常见的日志等级如下:info : 常规消息Warning:这个信息一般而言不会影响服务的运行,但是有必要要让用户知道,否则可能会造成某些问题的出现。Error :比较严重了,可能需要立即处理,但是也有可能这颗Error是不会影响我们的服务继续往下运行的。Fatal:致命问题,服务无法继续往下运行Debug:这个信息正常情况下我们不需要但是在调式的运行中会需要。这就是一般的日志等级的概念。

2024-01-15 12:23:47 868 1

原创 管道进行进程间通信(中)(实现一个简单的进程池)

在上一篇的博客中我说明了一些关于管道的特征特点如下:其中对于3和4特征这里只需要知道即可,我会在后面的博客讲解。然后我们测试了管道的前三种情况:第一种:读写端正常,管道为空,读端就要阻塞.第二种:读写端正常,管道如果被写满,写端就要阻塞第三种:读端正常,写端关闭,那么读端就会读到0,表明读到了文件(pipe)结尾,但是此时的读端是不 会被阻塞的。

2024-01-08 09:20:10 884

原创 管道进行进程间通信(上)

首先一个文件是可以被一个进程打开并访问的,那么现在的问题是一个文件能否被多个进程打开并访问呢?如果能的话,那么这个文件不就是一个共享的空间吗?只要一个进程往这个文件中写数据,然后另外一个进程从这个文件中读取数据。不就实现了将一个数据从一个进程移动到另外一个进程上了吗?但是使用这种基于一个实体文件的方式有一个致命的缺点那就是,没写一个数据到文件中,这个数据就需要先刷新到磁盘上,然后再从磁盘将这个数据写到内存中,让另外一个进程读取这个数据。这样的方式就会伴生出很多的效率问题。但是我们可以借助这个思想。

2024-01-01 15:29:22 752

原创 动静态库的简单制作

以下就是两个小点我们知道.o文件在形成可执行程序的时候,要么使用的是动态连接,要么使用的是静态连接,那么我们如何去看呢?这里使用的是ldd命令。其中的第一行和第三行我们不需要理解第三行是Linux中的加载器,第二行是c标准库,但是为什么没有看到我们写的那个静态库mymath的连接呢?首先第一个gcc在连接程序的时候默认使用的是动态的连接。使用ldd也证明了这一点。我们的a.out这个程序可以执行说明在这个可执行程序中已经连接了我们的静态库。由此我们能够得到一个结论,

2023-12-27 10:57:28 822

原创 文件系统和软硬链接(下)

在这里我们首先学习两个新的知识点第一个:第二个:下面我们再来理解思考下面的四个问题:我们首先来解决第一个问题如果新建一个文件Linux系统会做什么呢?

2023-12-18 21:21:26 852

原创 磁盘及文件系统(上)

这次博客我们将重点理解Ext2文件系统。首先我们要理解什么是文件系统。在之前我们一直理解的文件都是一个被打开的文件,而os为了能够管理这样的文件创建了struct_file这样的结构体对象在内核中描述被打开的文件,这个结构体对象中包含了被打开文件的基本属性,和绝大多数的属性(文件的大小,文件的偏移量,文件的权限,以及和内存块相关联的内容),包括对应的缓冲区。以上都是描述的被进程打开的文件的状态,那么没有被打开的文件?对于没有被打开的文件(磁盘中储存的文件)我们要关心下面几个关键。等等。

2023-12-16 15:35:12 791

原创 部分c++11特性介绍

下面来解释一下这个结论。

2023-12-04 11:36:22 814

原创 位图/布隆过滤器+海量数据处理总结

但是如果出现了4台服务器都无法完全储存这些信息了,需要扩展服务器,而为了不出现错误,所有用户信息的映射规则自然也是需要做出改变的,此时如果还是使用上面的哈希方法在扩展服务器的时候代价是很大的。解决思路就是:如果布隆过滤器最后返回的是不在代表此时的结果是准确的,不会做任何的处理,但是如果最后返回的是一个在,那么此时为了能够所有的结果都是准确的,这里选择的就是对布隆过滤器返回在的结果都交给服务器端在去做一个准确的判断,如果这个值在,那么这就是真的在了,如果这个值不在那么这个值就是不在。但是query不一样。

2023-11-27 11:22:32 435

原创 封装实现unordered_map和set

首先哈希是一个关联式容器,各个数据之间是具有关系的,和vector那些序列式容器不一样。首先unordered_map中的迭代器是一个单向的迭代器。其次在unorderede_map和set中是无序的(因为底层不是红黑树,而是哈希了)不再进行排序了。用法和set/map一样(除了不能使用--之外)。然后下面是对于map和unorder_ed map在性能上面的差异。

2023-11-20 15:22:58 76

原创 模拟实现一个Linux中的简单版shell

以上我们就能够完成一个比较简单的shell了,这里我们也知道了os中的shell也是一个进程,它能够不同的运行的原理是因为它是一个死循环,所以为了防止shell挂了,所以shell会创建子进程去完成用户输入的命令(如果shell不创建子进程执行命令,除了shell只能执行一次之外,还有shell会存在挂掉的风险,如果shell挂掉了,就没有软软件做命令行解释了),而因为每一个进程都是具有独立性的所以即使子进程挂了也不会影响shell的运行。这里需要注意的是argv是一个指针数组,而我们要获得的?

2023-11-16 16:55:39 943

原创 红黑树插入节点的模拟实现

情况1:uncle节点存在为红(因为其它几个节点(gpc)的颜色是固定的,c为红色(新插入,或者下面调整上来{原因在上面说过了}),p一定是红色,那么g一定是黑色。情况2:uncle节点不存在/u存在为黑色我们来看情况2的第一种如果uncle是不存在的。此时的cur就是新增解决方式也很简单就是一个左旋(以g为轴)即可下面是情况2的第二种如果uncle是存在且为黑色的。此时的cur就不是新增了,因为cur的变色是在a或者b的下面新增然后通过变色不断影响上来的。下面我们假设右子树只存在u这一个黑色节点。

2023-11-12 12:29:12 159

原创 AVL树节点插入方式解析(单旋转和双旋转)

此时的抽象图就是对实际情况的归类,但是实际情况是存在无数种的,因为h可以等于0,1,2,3,4,5,6.当h等于2的时候,AVL树都存在三种,以下的三种都是可以放到abc,那三个位置的。但是这样打印出来一个升序的结果,只能证明这是一个搜索树,不能证明这一个AVL树,所以我们还需要些一个验证平衡的代码,即求出每一个节点的左右高度差(右子树高度减去左子树高度),如果不等于平衡因子,则证明我们的AVL树出现了错误。我们分开是因为虽然旋转的过程是一样的,到那时需要按照不同的情况,去处理不同的平衡因子。

2023-11-07 13:23:53 111

原创 map和set的使用

set是包含在头文件set中的首先我们来看一下set的原型:可以看到set的原型是一个类模板,而这里的第一个模板参数给了一个T,这就是我们在二叉搜索树那里学的key。然后Compare是一个仿函数,因为set的底层是一个搜索树,而搜索树是需要去比较key的大小的。然后最后一个是空间配置器。空间配置器是用于给容器申请内存的(我们暂时不用管),而仿函数内部已经默认有了一个所以我们也不需要管。所以我们在使用set的时候,只用给第一个即可。下面我们来看set的接口。

2023-10-31 18:27:54 81

原创 Linux中进程的控制(上)

这里我们引入一下:首先我们写一段会出现异常的代码:这里我们的代码除0错误会异常。此时编译运行一下会发现最后系统给我们报出了一个浮点数异常。还有一种这里不能写入是因为0号区域是属于代码段的,是不能写入的。这里的错误就是段错误。所以这里的程序崩溃了,本质就是进程异常了,而一旦进程异常了os是绝对不会继续让这个进程运行的。此时的这个进程只能被os杀掉。这也是为什么我们的异常代码无法运行的。那么这里os是如何杀掉进程的呢?其实当某一个进程异常之后,我们的os是通过信号的方式来杀掉我们的进程的。

2023-10-27 15:46:38 67

原创 模拟实现二叉搜索树(非kv模式)(上)

首先二叉搜索树肯定是一棵二叉树,对于二叉树我们应该是陌生了。而我们在学习二叉树的时候知道,如果只是一棵普通的二叉树,用来储存数据是没有任何意义的,因为如果我们将数据放到一个普通的二叉树上,那么当我们需要查找这个值的时候我们只能将整棵树都遍历一遍,我们才能找到这个这个节点在二叉树中的位置。这和我们普通的使用数组没有什么区别。二叉搜索树则不同二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:1.若它的左子树不为空,则左子树上所有节点的值都小于根节点的值。

2023-10-25 08:06:09 55

原创 多态的使用以及多态底层的实现(下)

下图:对于第10,11,2,3问题在我的上一篇博客中说明了。希望这篇博客能对您有所帮助,如果您觉得写的不好请见谅,如果发现了任何的错误欢迎指出。

2023-10-23 22:04:50 198

原创 多态的使用以及多态底层的实现(上)

我们让不同的对象去完成同一件事情,这件事情的结果是不一样的,例如买火车票,我们学生买火车票,普通人买火车票,或是军人买火车票最后结果都是不一样的。这里需要记住的一点就是不构成重写就是重定义,因为重写和重定义的条件是存在相同之处的。可以说重写是在重定义的要求上关系可以看成下面的图:所以这里我们看父类和子类的函数名是否是相同的,如果相同就看是否是符合重写的要求,如果不满足那就是重定义。这里还要提出两个关键字第一个关键字就是final,这个关键字的作用是:修饰虚函数,表示该虚函数不能被重写。

2023-10-20 12:28:15 144

原创 c++中的继承(下)

1.很多人说C++语法复杂,其实多继承就是一个体现。有了多继承,就存在菱形继承,有了菱形继承就有菱形虚拟继承,底层实现就很复杂。所以一般不建议设计出多继承,一定不要设 计出菱形继承。否则在复杂度及性能上都有问题。多继承可以认为是C++的缺陷之一,很多后来的面向对象语言都没有多继承,如Java。

2023-10-16 18:54:34 81

原创 c++中的继承(上)

继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复用,继承是类设计层次的复用总结一下上面的话语:继承的本质也就是复用。即假设我在这里写了两个类,这两个类中含有公共的函数,那么我们将这个公共的函数抽取出来。形成一个新的类,然后让另外的两个类去调用这个函数。我们使用下面的例子来详细解释一下什么是继承。

2023-10-12 19:07:50 34

原创 模板如何做到声明和定义分离

然后编译器就会生成一个汇编指令,上图中的注释和,其中的问好也就是这个函数定义的地址,因为需要这个函数的地址所以编译器会从这里往上去寻找,是否存在这样的函数。对于func函数在链接的时候,在stack.cpp中发现了func的函数地址,所以这里可以通过,,但是因为我们的Add函数模板并没有实质的生成一个Add函数(不知道T的类型),所以在链接的时候,编译器没有发现Add函数的函数地址,最后就报错了。首先我们在之前学习模板的时候说过,在使用模板的时候我们要做到声明和定义不分离,但是这是为什么呢?

2023-10-12 08:47:44 136

原创 通过对list和vector正向迭代器的复用实现反向迭代器

首先我们在刚开始学习stl的时候,知道stl中含有6大组件,其中容器,迭代器和算法都是stl的六大组件之一。那么这里我们思考一个问题:迭代器的意义是什么呢?我们知道容器的意思是储存数据,而算法的作用是对数据进行处理,例如对vector进行排序,对list进行排序。如果我们将算法写到容器实现中,那么就会出现很多重复的代码。所以容器和算法是分离的。

2023-10-09 21:28:16 42

原创 动态规划问题(1)子数组系列

这几天刷了子数组系列的动态规划题目,在这里写下这篇博客,总结记录一下做这些题目的经验,同时也相当于复习。

2023-10-06 14:21:15 102 1

原创 模拟实现一个双端队列(理解使用仿函数)

因为我们在我们的命名空间中所写的那个仿函数是不具有将指针解引用然后比较的功能的,所以这里就是按照三个对象new出来的空间所在的序列大小进行的比较,所以会出现随机的答案。因为我在实现的时候,如果用户不传入额外的显示实例化,那么就会采用默认的less类,那么最后建立的就是大堆,如果用户最后显示实例化的时候写了我所定义的第二个greater函数,那么优先级顺序就会被修改。这两个函数更加的简单,只需要返回vector中的size函数,以及调用vector的empty函数就可以了。下面我们来实现一个最简单的仿函数。

2023-09-25 11:59:19 47

原创 在Linux系统中使用gdb调试一个代码

首先我们知道在使用vs时,我们时可以通过调式一段代码来找出我们这段代码的逻辑错误在哪里的,但是在Linux中没有对应的图形化界面,我们应该怎么去调试一个代码呢?这里就需要使用道Linux中的一个工具叫做gdb。首先要检测你的操作系统中是否安装了gdb。

2023-09-18 18:48:45 78

原创 简单分治归并题目解析(c++实现)

第一步肯定还是要弄懂什么是分治归并思想,这个思想最经典的地方也就是归并排序的实现了。那么我们现在就来复习一下归并排序的实现方法。首先归并排序的第一步也就是分治,例如上图将数组中的元素不断的划分直到每一个元素都被划分成单独的一个一个之后再将其不断地合并直到最后完成归并排序。

2023-09-17 12:51:03 87

原创 简单分治快排问题解析(c++实现)

首先我们要知道什么是分治快排思想,这个思想其实就是在模拟实现qsort算法的时候使用的一个方法,在模拟实现qsort的时候,我们知道第一步是需要使用一个随意选择(三数取中)的方法去选择一个随机数作为key的,然后我们需要遍历待排序的数组,将整个数组分成三个部分分别是小于key的元素,等于key的元素,大于key的元素。那么我们使用的将整个数组分成三个部分的这个思想就是分治快排思想。其实这个思想还有一个方法名字叫做三向划分数组。这个方法的实现请看下面的图,

2023-09-17 10:37:49 102

原创 Linux系统文件夹权限以及shell外壳的理解

简单介绍Linux系统中文件夹和普通文件的权限的作用以及修改的方法

2023-09-08 20:22:58 81

原创 前缀和题目解析

这几天学习了前缀和其中包括一维前缀和,以及二维前缀和。

2023-09-02 08:30:26 41

原创 滑动窗口题目

最近刷了两道非常经典的滑动窗口题目。感觉对自己帮助非常大,所以写下这篇博客来详细解释一下这两道题目,同时验证自己是否完全理解这两道题目。

2023-08-29 13:16:26 37

原创 模拟实现简单的list(模板)

list是一种序列式容器,可以在常数时间内在任意位置进行插入和删除操作,并且支持前后双向迭代。list的底层是双向链表结构,每个元素存储在独立的节点中,节点通过指针指向前一个元素和后一个元素。list与forward_list非常相似,最主要的区别在于forward_list是单链表,只能进行向前迭代,因此更简单高效。与其他序列式容器(如array、vector、deque)相比,list通常在任意位置插入和删除元素的效率更高。

2023-08-20 20:52:00 70

原创 模拟实现vector

首先要知道vector是什么。

2023-08-18 15:15:47 29

原创 模拟实现一个简单的string类

因为计算机的内存肯定是无法储存一个字母A的,内存中储存的只有0和1,由0和1组成了不同的值,在让不同的值映射为不同的符号,例如上面的字符0映射的数字也就是64。但是这么写还有一个很不好的点也就是,如果我输入的字符串非常的长,那么就会造成多次的扩容,如果你预先开了空间那么又会造成可能开的空间过大,而输入过少浪费的情况。=的重载,思路也都是复用了strcmp,因为我们写的这个只是针对于char*的所以使用这个,如果你要将string写为模板的话,这个是不合适的。这里模拟实现的是UTF-8类型的。

2023-08-16 18:26:40 51

原创 模板的简单使用

这篇博客主要是简单的介绍函数模板和类模板的使用。

2023-08-03 11:54:01 34

原创 c++内存管理基础

public:,_size(0)//开辟空间private:int* _a;int _size;//这只是一个简单的栈int main()free(st);delete sst;return 0;从监视上就可以看到,st并没有调用构造函数,而sst在创建空间之后还自动的调用了构造函数。而这也是为何要使用new而不是使用malloc,malloc只是将栈的空间创建好了但是对于内部的处理一个也不会做,而new则会在创建空间之后自动的调用构造函数。

2023-08-01 20:14:22 39

原创 初学类和对象(下)

在之前所写的日期类中已经包含了类和对象的大部分知识点,但是任然有1欠缺下面便是类和对象的一些欠缺知识点。

2023-07-29 19:47:18 37

空空如也

空空如也

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

TA关注的人

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