- 博客(339)
- 收藏
- 关注
原创 【云备份】项目展示&&项目总结
项目模块:1.数据管理模块:内存中使用hash表存储提高访问效率,持久化使用文件存储管理备份数据2.业务处理模块:搭建 http 服务器与客户端进行通信处理客户端的上传,下载,查看请求,并支持断点续传3.热点管理模块:对备份的文件进行热点管理,将长时间无访问文件进行压缩存储,节省磁盘空间。2. 客户端1.数据管理模块:内存中使用hash表存储提高访问效率,持久化使用文件存储管理备份数据2.文件检索模块:基于 c++17 文件系统库,遍历获取指定文件夹下所有文件。
2025-05-07 22:25:48
415
原创 【云备份】客户端开发
涉及序列化,我们服务端是使用JSON,但是我们vs2022没有jsoncpp这个库(我不想安装),所以,我们不使用JSON,我们直接自定义序列化格式:key value,每个key之间使用\n来分割。先讲讲数据管理模块,并不是所有的文件每次都需要上传,我们需要能够判断,哪些文件需要上传,哪些不需要,因此需要将备份的文件信息给管理起来,作为下一次文件是否需要备份的判断。首先我们打开服务端,把没有用的东西都删干净,包括备份的文件信息啊什么的。好,我们现在去启动客户端,下面这个是客户端进程的目录。
2025-05-07 20:11:28
883
原创 【云备份】服务端业务处理模块设计与实现
我知道大家可能不太了解html,不了解也没有关心,我们完全可以去别人的官网上面看看,它们是怎么实现的,然后随便复制一些下来就行,我这里就简单的copy了一些,就是为了让大家简单的看看一下我们大概的html的界面。当服务器收到一个POST方法的/upload请求,则我们认为这是一个文件上传请求,我们就应该解析请求,获得文件数据,将数据写进文件里面,这个文件就备份成功了。我们随机点击那个蓝色的,可是我们点进去,它却不是给我们下载,而是直接给我们看这个文件里面有什么。
2025-05-05 22:30:21
631
1
原创 【云备份】服务端数据管理模块设计与实现
首先我们首先需要对 struct BackupInfo结构进行填充,这个需要一个构造函数 NewBackUpInfo。以文件访问 URL 作为 key,是因为客户端浏览器下载文件时总是以 URL 作为请求。数据信息结构体:struct BackupInfo结构中包含要管理的文件各项属性信息;现在所有的信息都存储在这个_backup_file文件里面里面了。我们这个函数目前是只测试了那些信息访问的接口,具体接口看下面。为了检测我们这个代码写的对不对,我们需要来测试一下。我们啥也不多说,直接看代码好吧!
2025-05-03 12:40:35
901
原创 【云备份】配置文件加载模块
一般来说,我们的用户都是输入类似于下面这种URL:http://192.168.122.136:9090/path,通过这样子的方式,默认访问到的是我们根目录下的path文件了吗?这是很危险的,所以我们会在程序运行时添加一个新的相对的根目录。上传的文件也可能是压缩文件,而我们对于上传的文件里面对于非热点文件,我们会进行压缩,如果非热点文件是压缩文件,那我们不能对其再次进行压缩。事实上,我们这个项目并没有使用数据库来存储任何信息,因为这个是一个入门项目,如果加上数据库,就会显得这个项目有点庞大了。
2025-05-02 16:09:26
1119
原创 【云备份】服务端工具类实现
不管是客户端还是服务端,文件的传输备份都涉及到文件的读写,包括数据管理信息的持久化也是如此,因此首先设 计封装文件操作类,这个类封装完毕之后,则在任意模块中对文件进行操作时都将变的简单化。文件实用工具类FileUtil访问我们这里不单单对普通文件进行处理,我们对目录文件也设计了接口。首先我们打开我们的云服务器看看这些都是我们之前实验下来的那些文件啊,我们现在把不必要的文件进行删除我们创建一个util.hpp,把我们上面的东西给搞进去。
2025-05-01 20:59:43
1217
原创 【网络】HTTP报文首部字段
由服务器返回的响应中,若报文首部字段 Cache-Control 中对 no-cache 字段名具体指定参数值,那么客户端在接收到这个被指定参数值的首部字段对应的响应报文后,就不能使用缓存。比如,对于使用首部字段 Accept-Language 的服务器驱动型请求,当 返回的页面内容与实际请求的对象不同时,首部字段 Content-Location 内会写明 URI。网关是转发其他服务器通信数据的服务器,接收从客户端发送来的请 求时,它就像自己拥有资源的源服务器一样对请求进行处理。对此,我们无从可知。
2025-04-29 18:22:36
635
原创 【网络】HTTP状态码
仅记录在 RFC2616 上的 HTTP 状态码就达 40 种,若再加上 WebDAV(Web-based Distributed Authoring and Versioning,基于万维网 的分布式创作和版本控制)(RFC4918、5842) 和附加 HTTP 状态码 (RFC6585)等扩展,数量就达 60 余种。别看种类繁多,实际上经 常使用的大概只有 14 种。接下来,我们就介绍一下这些具有代表性 的 14 个状态码。
2025-04-28 19:56:31
702
原创 Git多人协作与企业级开发模型
这种模式为哪种开发提供更好的⽀持?这时推送失败,因为你的小伙伴的最新提交和你推送的提交有冲突,解决办法也很简单,Git已经提示我们,先用 git pull把最新的提交从 origin/dev 抓下来,然后,在本地进行合并,并解决冲突,再推送。这时,你的⼩伙伴已经修养的差不多,可以继续进⾏⾃⼰的开发⼯作,那么他⾸先要获取到你帮他开 发的内容,然后接着你的代码继续开发。最后不要忘记,虽然我们是在分⽀上进⾏多⼈协作开发,但最终的⽬的是要将开发后的代码合并到 master上去,让我们的项⽬运⾏最新的代码。
2025-04-24 18:13:27
868
1
原创 Git远程操作与标签管理
我们⽬前所说的所有内容(⼯作区,暂存区,版本库等等),都是在本地!可以简单理解为,我们每个⼈的电脑上都是⼀个完整的版本库,这样你⼯作的时候,就不需要联⽹ 了,因为版本库就在你⾃⼰的电脑上。好在这个世界上有个叫GitHub的神奇的⽹站,从名字就可以看出,这个⽹站就是提供Git仓库托管服务 的,所以,只要注册⼀个GitHub账号,就可以免费获得Git远程仓库。⽐⽅说你在⾃⼰电脑上改了⽂件A,你的同事也在他的电脑上改了⽂件A,这时,你们俩之间只需 把各⾃的修改推送给对⽅,就可以互相看到对⽅的修改了。
2025-04-22 23:45:34
1006
原创 【Linux】计算机基本知识补充
下一层是高速缓存,它多数由硬件控制,主存被分割成高速缓存行(cacheline),其典型大小为64字节,地址0至63对应高速缓存行0,地址64至127对应高速缓存行1,以此类推。在第4步中,中断控制器把该设备的编号放到总线上,这样CPU可以读总线,并且知道哪个设备刚刚完成了操作(可能同时有许多设备在运行)。当中断处理程序(中断设备的设备驱动程序的一部分)开始后,它取走已入栈的程序计数器和PSW,并保存之,然后查询设备的状态。中取出指令,解码以确定其类型和操作数,接着执行之,然后取指、解码并执行下一条指令。
2025-04-22 19:39:45
1372
原创 【Linux】虚拟内存——页表与分页
把物理地址暴露给进程会带来下面几个严重问题。第一,如果用户程序可以寻址内存的每个字节,它们就可以很容易地(故意地或偶然地)破坏操作系统,从而使系统慢慢地停止运行(除非使用特殊的硬件进行保护,如IBM 360的锁键模式)。即使在只有一个用户进程运行的情况下,这个问题也是存在的。第二,使用这种模型,想要同时运行(如果只有一个CPU就轮流执行)多个程序是很困难的。在个人计算机上,同时打开几个程序是很常见的(一个文字处理器,一个邮件程序,一个网络浏览器),其中一个当前正在工作,其余的在按下鼠标的时候才会被激活。
2025-04-22 16:31:18
858
原创 Git分支管理
你创建了⼀个属于你⾃⼰的分⽀,别⼈看不到,还继续在原来的分⽀上 正常⼯作,⽽你在⾃⼰的分⽀上⼲活,想提交就提交,直到开发完毕后,再⼀次性合并到原来的分⽀ 上,这样,既安全,⼜不影响别⼈⼯作。添加⼀个新功能时,你肯定不希望因为⼀些实验性质的代码,把主分⽀搞乱了,所以,每添加⼀个新 功能,最好新建⼀个分⽀,我们可以将其称之为 feature 分⽀,在上⾯开发,完成后,合并,最后,删除该 feature 分⽀。在Git中,每个bug都可以通过⼀个新的临时分⽀来修复,修复后,合并分⽀,然后将临时分⽀ 删除。
2025-04-20 10:59:47
977
原创 【网络】IP层的重要知识
并且,每增加一个新的网络,就需要将这个新被追加的网络信息设置在所有的路由器上。如果有一个新的网络被追加到原有的网络中时,只要在新增加网络的路由器上进行一个动态路由的设置即可。况且,网络上一旦发生故障,只要有一个可绕的其他路径,那么数据包就会自动选择这个路径,路由器的设置也会自动重置。发送数据包时所使用的地址是网络层的地址,即IP地址。动态路由如图所示,会给相邻路由器发送自己已知的网络连接信息,而这些信息又像接力一样依次传递给其他路由器,直至整个网络都了解时,路由控制表也就制作完成了。
2025-04-17 17:06:37
1007
原创 Git的安装以及基本操作
1、Git是什么?Git是目前世界上最先进的分布式版本控制系统(没有之一)。可以有效、高速地处理从很小到非常大的项目版本管理。Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开源码的版本控制软件。Torvalds 开始着手开发 Git 是为了作为一种过渡方案来替代 BitK2、Git与SVN的主要区别。
2025-04-09 12:15:03
867
原创 二分答案算法
如果「解空间」在从大到小的变化过程中,「判断」答案的结果出现「二段性」,此时我们就可以「二分」这个「解空间」,通过「判断」,找出最优解。因此,在解空间中,根据 ret 的位置,可以将解集分成两部分,具有「二段性」。在解空间中,根据 ret 的位置,可以将解集分成两部分,具有「二段性」,那么我们就可以「二分答案」。在解空间中,根据 ret 的位置,可以将解集分成两部分,具有「二段性」,那么我们就可以「二分答案」。的位置,可以将解集分成两部分,具有「二段性」,那么我们就可以「二分答案」。
2025-03-29 21:05:35
775
原创 set与map的底层数据结构
红⿊树(简称RBT),也是⼀棵⼆叉搜索树。它是在搜索树的基础上,使每个结点上增加⼀个存储位表⽰ 结点的颜⾊,可以是Red或者Black,通过对任意⼀条从根到叶⼦的路径上各个结点着⾊⽅式的限 制,确保没有⼀条路径会⽐其他路径⻓出2倍,因⽽是⼀棵接近平衡的⼆叉搜索树。红⿊树相对于AVL树来说,牺牲了部分平衡性以换取插⼊/删除操作时少量的旋转操作,整体来说性能 要优于AVL树。1. 每个结点要么是红⾊要么是⿊⾊;2.根节点和叶⼦结点(这⾥的叶⼦结点不是常规意义上的叶⼦结点,⽽是空结点,如下图中的NIL)
2025-03-27 16:55:11
1157
原创 最短路问题——单源最短路
是的,所以我们上面也说了: Bellman-Ford算法是比较暴力的把所有的边都更新(即先后对所有的顶点的相邻顶点进行松弛),而不像Dijkstra算法的贪心那样每次选的都是最短的,也因此它一遍过后可能得不出最短的路径,可能需要进行多次迭代。
2025-03-16 13:44:00
919
原创 最小生成树
对一个具有 n 个点的连通图进行遍历,对于遍历后的子图,其包含原图中所有的点且保持图连通,最后的结构一定是一个具有 n-1 条边的树,通常称为生成树。说白了,就是有n个结点,但是只有n-1条边,并且这n个结点是连通的。
2025-03-13 12:16:45
609
原创 数组模拟实现链表
两个⾜够⼤的数组,⼀个⽤来存数据,⼀个⽤来存下⼀个结点的位置变量 h ,充当头指针,表⽰头结点的位置变量 id ,为新来的结点分位置注意我们这里是有一个头结点的(即h和id所指的位置)int h;// 头指针int id;// 下⼀个元素分配的位置// 数据域和指针域// 下标0位置作为哨兵位// 其中ne数组全部初始化为0,其中ne[i] = 0就表⽰空指针,后续没有结点// 当然,也可以初始化为- 1作为空指针,看个⼈爱好/*
2025-03-10 20:42:41
869
原创 拓扑排序算法
用unordered_map就比较万能了,完全像刚才想象出来的邻接表结构,我们这里是一个int的数后面挂了一个int数组,那不就和一个节点挂着一个节点的效果一样的吗。我们可以把给的信息抽象称一张有向图,题目问能否完成所有课程学习意思就是能不能把这个课程排个序,说白了就是能否拓扑排序,能否拓扑排序也就是是否这个图是否是有向无环图 —> 有向图中是否有环?,有向图就是边都是有方向的。直接对图来一次拓扑排序,当拓扑排序过程中发现没有入度为0的点的时候,但是图中还有剩余点的时候,此时这个图中一定会有环形结构。
2025-03-10 20:41:45
978
原创 Trie树(字典树)
Trie树,又叫字典树前缀树(Prefix Tree)单词查找树或键树,是一种多叉树结构。如下图:上图是一棵Trie树,表示了关键字集合{“a”, “to”, “tea”, “ted”, “ten”, “i”, “in”, “inn”}。根节点不包含字符,除根节点外的每一个子节点都包含一个字符。从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串。每个节点的所有子节点包含的字符互不相同。通常在实现的时候,会在节点结构中设置一个标志,用来标记该结点处是否构成一个单词(关键字)。
2025-03-09 10:32:18
1088
原创 并查集算法
并查集是一种树形数据结构,用于处理一些不相交集合的合并及查询问题。通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,这样就可以查询某个元素所在的集合、与这个元素在一个集合中的元素,以及更多。只说这些肯定不行,接下来我将详细介绍。
2025-03-07 20:18:32
708
原创 单调栈算法题
单调栈(Monotone Stack):其实就是一种特殊的栈,只不过在栈的「先进后出」规则基础上,要求「从栈底到栈顶的元素是单调递增(或者单调递减)」。其中满足从栈底到栈顶的元素是单调递增的栈,叫做「单调递增栈」。满足从栈底到栈顶的元素是单调递减的栈,叫做「单调递减栈」。注意:这里定义的顺序是从「栈底」到「栈顶」。有的文章里是反过来的。本文全文以「栈底」到「栈顶」的顺序为基准来描述单调栈。
2025-03-05 21:20:43
1007
原创 高精度(加,减,乘,除)算法题
之前我们遇到数字的时候,遇到的数的时候我们可以使用int来存储,如果说这个数字达到了,那我们可以使用long long来存储。但是要是数值再比这个都大的时候,比如说当数据的数值达到了,这样子我们用什么去存储啊???当数据的值特别⼤,各种类型都存不下的时候,此时就要⽤⾼精度算法来计算加减乘除:先⽤字符串读⼊这个数,然后⽤数组逆序存储该数 的每⼀位;利⽤数组,模拟加减乘除运算的过程。⾼精度算法本质上还是模拟算法,⽤代码模拟⼩学列竖式计算加减乘除的过程。
2025-02-20 18:12:25
651
原创 算法竞赛里面的sort函数
sort在默认的情况下是按照升序排序,如何按照降序排序呢?如果是结构体类型数据进⾏排序呢?怎么办?使⽤⾃定义排序⽅式参数解释:指向要排序范围的第一个元素的迭代器或指针。:指向要排序范围的最后一个元素之后位置的迭代器或指针。:自定义的比较函数或函数对象,用于比较两个元素。sort的第三个参数是⼀个可选的⾃定义⽐较函数(或函数对象),⽤于指定排序的规则。如果不提供这个参数,std::sort默认会使⽤⼩于运算符(<)来⽐较元素,并按照升序排序。这个⽐较函数,接受两个参数,并返回⼀个布尔值。
2025-01-18 11:06:40
730
原创 算法竞赛里面的STL——堆和priority_queue
此外,双向链表还能迅速定位到删除操作后新相邻的元素,便于我们判断它们是否为未出列的异性,并据此更新堆中的配对信息。那我为什么不建一个大根堆,只要我保证这个堆的大小是k,这样子堆顶的元素就会一直是第k小的。由于我们使用的是大根堆,所以20是优先级最高的元素。时间复杂度:由于底层是一个堆结构,所以删除优先级最高的元素的时间复杂度为O(log n),其中n是优先级队列中的元素数量。所谓第k大,我们完全可以创建一个小根堆,然后保持堆的大小是k,然后这样子就能保证heap.top()就是第k大的元素了。
2025-01-17 20:34:37
1078
原创 贪心算法(一文速通)
贪心算法(Greedy Alogorithm)又叫登山算法,它的根本思想是逐步到达山顶,即逐步获得最优解,是解决最优化问题时的一种简单但是适用范围有限的策略。贪心算法没有固定的框架,算法设计的关键是贪婪策略的选择。贪心策略要无后向性,也就是说某状态以后的过程不会影响以前的状态,至于当前状态有关。贪心算法是对某些求解最优解问题的最简单、最迅速的技术。某些问题的最优解可以通过一系列的最优的选择即贪心选择来达到。但局部最优并不总能获得整体最优解,但通常能获得近似最优解。
2025-01-16 11:59:24
1332
原创 动态规划七——背包问题
其实,根本不需要负的下标,我们根据实际情况来看,如果这个任务的利润已经能够达标了(即使减去当前任务的利润后小于0),我们仅需在之前的任务中挑选出来的利润至少为0就可以了。背包问题其实是动态规划的核心,但是由于背包问题的种类繁多,而且背包问题的难度层次不齐,有的题目已经升级到竞赛难度了,所以我们这里只讲01背包问题和完全背包问题。给你一个“背包”,这个“背包”的体积是V,给你一堆“物品”,这些“物品”每一个都有价值w和体积v,让你选择一些放入“背包”,得到最大(最小)价值。顺序无关是组合问题的一个特点。
2025-01-12 20:49:57
1287
原创 动态规划五——回文串问题
我不知道大家有没有看到上面这个dp[i][j] = dp[i + 1][j - 1],也就是说dp[i+1][j-1]一定要比dp[i][j]先算出来!我不知道大家有没有看到上面这个dp[i][j] = dp[i + 1][j - 1],也就是说dp[i+1][j-1]一定要比dp[i][j]先算出来!则我们需要设置另外一个变量j(注意0<j<=i),我们让j从1开始往右边遍历,如果发现【j,i】是回文串,则我们只需要在【0,i-1】区间的基础上加上一刀即可,我们就让dp[i]=dp[j-1]+1。
2024-12-31 11:05:12
1168
原创 动态规划四——子序列系列
目录题目一——300. 最长递增子序列 - 力扣(LeetCode)题目二——376. 摆动序列 - 力扣(LeetCode)题目三—— 673. 最长递增子序列的个数 - 力扣(LeetCode)题目四——646. 最长数对链 - 力扣(LeetCode)题目五——1218. 最长定差子序列 - 力扣(LeetCode)题目六——873. 最长的斐波那契子序列的长度 - 力扣(LeetCode)题目七——1027. 最长等差数列 - 力扣(LeetCode)题目八——446. 等差数列划分 II - 子序
2024-12-29 18:05:41
1212
原创 动态规划三——子数组系列
两种情况下的最⼤值,就是我们要的结果。但是,由于数组内有可能全部都是负数,第⼀种情况下的结果是数组内的最⼤值(是个负数),第⼆种情况下的 gmin == sum ,求的得结果就会是 0。虽然它没有任何相邻元素来形成翻转的比较符号,但按照题目的要求,我们需要返回一个答案,所以这里返回 1,表示数组中最长的(也是唯一的)“湍流”子数组的长度。nums[i] < 0 时,此时我们要看 g[i-1] 的值(因为负负得正,如果我们知道以 i-1 为结尾的乘积为负数的最长子数组的长度,加上 1 即可)。
2024-12-20 10:22:37
1098
原创 动态规划二——简单多状态dp问题
上⼀个问题是⼀个「单排」的模式,这⼀个问题是⼀个「环形」的模式,也就是⾸尾是相连的。但是我们可以将「环形」问题转化为「两个单排」问题:首先我们将上面那些整合成一个函数int rob1(vector<int>&nums,int left,int right)
2024-12-18 14:35:47
763
原创 动态规划一 ——斐波那契数列模型+路径问题
dp[i][j] = min(dp[i - 1][j], min(dp[i - 1][j - 1], dp[i - 1][j + 1])) + matrix[i][j] 这个有越界情况啊。否则,万⼀ 发⽣了溢出,我们的答案就错了。不过注意一下:现在状态转移方程变成了dp[i][j]=max(dp[i-1][j],dp[i][j-1])+frame[i-1][j-1]由于我们要求的是有多少种⽅法,因此状态转移⽅程就呼之欲出了: dp[i][j] =dp[i-1][j] + dp[i][j - 1]。
2024-12-15 21:27:42
1383
1
原创 BFS算法题
正常来说,在我们会了单源BFS的使用后,面对多个起点到一个终点的最短路问题也就是多源BFS,我们最先想到的就是暴力做法,也就是将多个起点分成一份份一个起点到一个终点的单源BFS问题,这样我们每个起点到终点的最短路都求出来再找最小值即可,但这种暴力几乎是一定超时的,最差时间复杂度都达到ON^3。用数组表示所连接的节点。这时我们就发现,如果多个起点一块进行BFS搜索,重复的路程不再经过,这时不仅得出的答案正确,而且时间复杂度大大降低,这也就是多源BFS的核心思路,多个起点同时用单源BFS的方法去找最短路。
2024-12-13 22:15:33
1052
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人