当前位置: 首页 > news >正文

递归、搜索和回溯算法《递归》

在之前的优选算法当中我们已经学习了一些基本的算法,那么接下来我们就要来学习算法当中的一大重要章节——递归、搜索和回溯算法,其实也就是大家常常听到的dfs、bfs;其实本质就是递归,在学习搜索、回溯等算法的过程当中我们会先来了解算法的一些名词,之后再通过算法题来明白算法具体是如何使用的,最后在通过几道练习题来巩固算法。在算法题的讲解当中还是通过题目解析、算法原理讲解、代码实现三步来带你完全理解对应的算法题。在本篇当中我们就来复习之前在C语言当中就学习到的递归,并且本次学习递归会和之前初次学习的角度不同,相信通过本篇的学习会让你不再惧怕递归,一起加油吧!!!


1.递归复习与再理解 

通过之前C语言的学习我们就知道递归其实就是函数递归,其本质就是函数自己调用自己。从刚开始学习递归的时候的斐波那契数列再到数据结构当中二叉树当中遍历二叉树、排序当中的快速排序与归并排序都是运用了递归,所以通过之前的学习其实现在我们已经有了基本的递归思维,只不过在之前的学习当中在运用递归的时候通常都要将递归的函数展开图给画出来之后才能理解递归,虽然这样也能理解递归的实现,但是当某个函数递归的展开图很复杂的时候,其实画函数展开图的方式其实反而是阻碍我们理解递归的。

因此接下来再次理解递归就从更加本质的方向去理解,以上我们已经回想起来了递归是什么,那么接下来在此将会通过为什么要使用递归、如何理解递归、如何写好一个递归三个过程来透彻的理解递归。

1.1 为什么要使用递归

首先总结之前使用递归的地方,我们就要思考为什么要使用递归?

在之前二叉树遍历,快速排序等使用递归其实都是一直在解决相同的子问题,此时相比使用迭代递归实现的代码就较为简练,因为每个子问题都是一样的,那么这时候就只需要实现一份代码就可以解决问题。

在遍历二叉树时遍历一棵树可以看作依次向访问二叉树的节点依次再遍历该节点的左子树和右子树,到遍历该节点的左节点和右节点时又可以将其的左子树看作一个要进行遍历的二叉树;执行的操作和与其父节点是相同的,遍历到右节点也如此。 在访问二叉树要解决的相同子问题是依次访问二叉树的根节点;左子树;右子树。到了左子树或者右子树当中进行的操作也是和之前是一样的,那么此时就适合使用递归来解决。

再快速排序当中每一步我们要进行的操作就是将给定的数组进行调整,调整之后使得返回的下标左侧的元素值小于返回下标的值;右侧的元素值大于返回下标的值。因此在快速排序当中要解决的相同子问题就是找出对应的基准值将原数组划分为两个部分。之后对子数组进行的操作也相同的,那么此时就可以使用到递归。

在归并排序当中需要解决的相同子问题就是把给定的左子数组形成有序序列,再把右子数组形成有序序列,最后再将左右两个有序序列形成有序序列。在此解决的子问题都是一样的,因此就适合使用递归。

1.2 如何更好的理解递归

通过以上我们就知道了为什么在一些场景当中要使用递归,那么接下来就来讲解如何更好的理解递归。

在之前写二叉树的前序遍历、中序遍历、后序遍历的时候我们都是通过画递归的函数展开图来理解递归具体的实现效果是什么样的。

//中序遍历
void InOrder(BTNode* root)
{if (root == NULL){return;}InOrder(root->left);printf("%d ", root->val);InOrder(root->right);
}

以上这样确实能让我们更好的理解,但是问题是如果每实现一个递归都要画递归的展开图也太繁琐了,有没有什么更加简单的方式理解递归呢?

其实是有的,那就是从宏观的角度去看递归具体的思考方式就是不要再去在意递归的具体展开过程,而是将递归当中一个黑盒,我们不需要知道黑盒当中具体是怎么实现的,我们只需要将对应的数据丢给它,相信它能实现得到我们要的结果,最后把结果得到即可。最后将函数的出口设计好即可。

总的来说宏观的看待递归的过程需要有以下的三点要注意:

1.不要在意递归的细节展开图
2.把递归的函数当作一个黑盒
3.相信这个黑盒一定能完成我们要求的任务

例如以上实现二叉树的中序遍历时,目的其实就是遍历二叉树的根节点、左子树、右子树,那么就只需要先调用对应的中序遍历函数相信它能将左子树的中序遍历结果输出给我们,之后我们只需要把当前节点的数据打印出来即可,之后再先调用对应的中序遍历函数相信它能将右子树的中序遍历结果输出给我们。最后我们再将中序遍历时当前节点值为NULL的情况进行特殊判断。

1.3 如何写好递归 

以上我们了解了如何宏观的理解递归,那么接下来我们就要来了解如何在宏观的角度下写好递归的代码

其实我们只需要进行以下的三个操作即可

1.找到相同的子问题(函数头的设计)
2.只关心某个子问题是如何解决的(函数体的书写)
3.注意函数的出口

接下来我们就按照以上的思路来试着实现快速排序和归并排序的伪代码

首先是快速排序当作要解决的相同子问题就是找到对应子数组内的基准值,并且在解决这个子问题的时候需要给函数提供数组起始下标和终止下标以及数组的指针。那么此时递归函数的函数头就需要有三个参数,即数组指针、起始下标、终止下标。解决该子问题就是在对应区间的数组内找到对应的基准值,因此函数体内就需要找出对应数组区间内的基准值元素下标。最后函数的出口就是当对应子数组内起始下标大于等于终止的下标时就返回。

伪代码实现如下所示:

而在归并排序当中要解决的相同子问题就是把对应区间内的数组排序好,并且在解决这个子问题的时候需要给函数提供数组起始下标和终止下标以及数组的指针。那么此时递归函数的函数头就需要有三个参数,即数组指针、起始下标、终止下标。接下来函数体内要实现的就是对对应的子数组进行排序。最后函数的出口就是当左区间的下标大于右区间的下标时。

 实现的伪代码如下所示:

1.4 二叉树递归算法题再理解

以上我们从宏观的方向再对递归进行了理解,那么接下来我们就试着对之前在二叉树算法题章节当中写过的算法题再写一遍,这次使用的是宏观的角度来写题。

注:在此就不再进行讲解,算法的链接可以看之前算法题章节

二叉树算法题-CSDN博客

2.递归算法练习题

以上我理解了递归,那么接下来就通过以下的算法题来巩固之前学习大的知识

2.1 汉诺塔

面试题 08.06. 汉诺塔问题 - 力扣(LeetCode)

题目解析 

通过以上的题目描述就可以看出该撒算法题压哦我们实现的是将给定的第一个圆盘A当中的所有圆珠移动到圆盘C上,最后圆盘C上圆珠的顺序要和原来圆盘A当中完全一直。也就是将数组A当中的元素移动到数组C当中,最终移动到数组C的元素顺序要和数组A完全一样。

接下来我们就来看看n=1,2,3时具体的圆珠是怎么在三个盘之间移动的

n==1

当n为1时只需要将A当中的盘珠直接移动到C即可

n==2

在n为2时就需要先将A当中的最上的那个圆珠移动到B上,之后再将A的最底下爱的圆珠移动到C,最后将B上的圆珠移动到C

n==3

当n==3的时候就只需要先将A当中前两个借助C移动到B,之后再将A的最后一个移动到C,最后将B当中的两个借助A移动到C

算法原理讲解

以上我们就了解该算法题要我们实现的是什么,那么接下来就来试着思考该算法题如何解决

在此通过以上n为1,2,3时候的情况就可以发现解决的过程其实都是通过相识的三步来解决的。第一步是将A当中的前n-1个借助C移动到B,再将A的最后一个移动到C,最后将B的n-1个借助A移动到C

那么在解决每步时候其实就是在解决相同的子问题,而且对于的问题内又是解决步骤相同的子问题,此时就可以使用递归来解决。

接下来就试着来将递归当中的三步分析是什么。

首先是递归当中函数头的设计,此时就要观察重复子问题当中包含哪些。通过以上的步骤图就可以看出在函数当着我们需要知道移动圆珠的个数以及借助的圆盘、目标圆盘。那么就可以得出函数的参数需要4个,分别是移动圆珠的个数、提供圆珠的圆盘、移动中借助的圆盘、目标圆盘。

接下来来分析函数体内该如何实现,也就是只需要观察一个子问题的执行流程,其实就只需要将以上子问题流程图当中的三步执行即可。首先是将n-1个从A借助C移动B,再将A内的最底下的那个移动到C,最后将B中的n-1个借助A移动到C

最后分析函数的出口

当n==1的时候只需要将A当中的最底下的那个移动到C,这就是函数的出口,执行完就从函数返回。

代码实现

以上我们就分析完了汉诺塔这道算法题该如何实现,那么接下来就来试着将以上的算法思路转化为代码

class Solution {
public:void hanota(vector<int>& A, vector<int>& B, vector<int>& C) {//在dfa函数内实现将A的n个圆珠移动到Cdfs(A,B,C,A.size());}//在dfs函数当中A表示提供圆珠的圆盘,B表示借助的圆盘,C表示目标圆盘,n表示圆珠个数void dfs(vector<int>& A, vector<int>& B, vector<int>& C,int n){//当n==1时直接将A的最后一个移动到Cif(n==1){   C.push_back(A.back());A.pop_back();return;}//函数有体实现//1:将A当中的n-1个借助C移动到Bdfs(A,C,B,n-1);//2:将A当中的最后一个移动到CC.push_back(A.back());A.pop_back();//3:将B当中的n-1个借助A移动到Cdfs(B,A,C,n-1);}
};

2.2 合并两个有序链表

21. 合并两个有序链表 - 力扣(LeetCode)

题目解析 

通过以上的题目描述就可以看出算法题让我们实现的就是将给定的链表进行反转

算法原理讲解

这道题其实在数据结构链表的学习当中我们就已经实解决过了,但是之前我们使用的迭代的方式实现的,而这次我们将从另一角度来解决。

我们先来看以上的示例1
在示例1当中这两个链表就需要从这两个链表的头节点开始,之后对比链表的节点大小之后再小的那个节点的next指针链接到之后剩余的链表的最小值节点当中。

 通过以上的步骤图就可以看出其实每一步进行的方式都是一样的,都是找出当中两个链表指针指向的节点当中小的那个节点,之后再该节点的next指针指向剩余的节点的最小值节点。

那么此时我们就发现再该算法题当中存在重复子问题,那么就可以试着使用递归来解决

接下来就试着来将递归当中的三步分析是什么。

首先是递归当中函数头的设计,此时就要观察重复子问题当中包含哪些。通过以上的步骤图就可以看出在函数当着我们需要知道当前两个链表当中指针指向数值小的那个节点。那么就可以得出函数的参数需要2个,分别是另外一个节点的指针,以及数值小的娘那个节点的next指针。函数的返回值就为数值小德那个节点的指针。

接下来来分析函数体内该如何实现,也就是只需要观察一个子问题的执行流程,其实就只需要将以上子问题流程图当中的两步执行即可。首先是将两个链表当中指针指向数值小的那个节点找出,再将该节点的指针的next指针指向剩余节点的返回值。

最后分析函数的出口

当有一个链表为空时就返回另外一个一个链表的节点即可

代码实现

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {//当有一个链表为空时返回if(list1==nullptr)return list2;if(list2==nullptr)return list1;//找出值更小的节点,将值最小的节点的next指针指向剩余节点的返回值if(list1->val<list2->val){list1->next=mergeTwoLists(list1->next,list2);return list1;}else{list2->next=mergeTwoLists(list1,list2->next);return list2;}}
};

2.3 反转链表

206. 反转链表 - 力扣(LeetCode)

题目解析 

通过以上的题目描述就可以看出该算法题要我们实现的是将链表进行反转,最后返回反转之后的链表头节点。

算法原理讲解

这道题在之前的链表专题我们也解决过了,只不过在之前的解决这道题时我们是使用创建n1、n2、n3的方式来解决,也就是使用迭代的方式解决的,而这次从不同的角度分析。

首先来看以上的示例1:

 通过以上的步骤图就可以看出其实每一步进行的方式都是一样的,都是将当前链表指向的节点之后的节点的next指针指向当前节点,再接收剩余节点的头节点。

那么此时我们就发现再该算法题当中存在重复子问题,那么就可以试着使用递归来解决

接下来就试着来将递归当中的三步分析是什么。

首先是递归当中函数头的设计,此时就要观察重复子问题当中包含哪些。通过以上的步骤图就可以看出在函数当着我们需要知道当前链表的节点。那么就可以得出函数的参数需要1个,是当前节点的指针

接下来来分析函数体内该如何实现,也就是只需要观察一个子问题的执行流程,其实就只需要将以上子问题流程图当中的两步执行即可。首先是将将剩余的节点反转再保存头节点,再将当前节点的之后的节点的next指针指向当前节点,最后将当前节点的next指针值为空

最后分析函数的出口

当链表指针的下一个节点为空时就返回当前的节点

代码实现

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* reverseList(ListNode* head) {//当此时当前节点为空时或者的下一个节点为空的时候就返回当前的节点if(head==nullptr || head->next==nullptr)return head;//将剩余的节点进行反转ListNode* ret=reverseList(head->next);//将当前节点的下一个节点的next指针指向当前节点head->next->next= head;//将当前节点的next指针值为空head->next=nullptr;return ret;}
};

注:在本道题当中节点个数可能会出现空,那么此时就需要在函数出口加一条当前节点为空时也返回head,并且要将该条件加到下一个节点为空的判断之前;否则就会出现空指针的解引用。

2.4 两两交换链表中的节点

24. 两两交换链表中的节点 - 力扣(LeetCode)

题目解析 

通过以上的题目解析就可以看出该撒算法题要我们实现的是将给定的链表相邻的两个节点位置两两交换,在此我们不能改变节点内的值。

接下来来看示例1:

要将以上的链表相邻节点两两交换,就需要先改变第一个和第二个节点的指针

接下来再继续修改剩余的两个节点指针

 

算法原理讲解 

在通过以上的示例1的分析就发现每次处理的问题都是一样的,都是将当前节点和下一个节点对应的指针进行修改,之后再将当前节点的next指针指向剩余节点。

那么此时该算法题当中解决的就是重复的子问题,在此就可以使用递归来解决,接下来来分析递归当中的三步依次是什么

首先是递归当中函数头的设计,此时就要观察重复子问题当中包含哪些。通过以上的步骤图就可以看出在函数当着我们需要知道当前链表的节点。那么就可以得出函数的参数需要1个,是当前节点的指针

接下来来分析函数体内该如何实现,也就是只需要观察一个子问题的执行流程,其实就只需要将以上子问题流程图当中的两步执行即可。首先是将将当前节点的下一个节点的next指针指向当前节点,之后再将当前节点的next指针指向剩余的节点,最后返回对应的头节点即可。

最后分析函数的出口

当链表当前节点的指针为空或者的下一个节点为空时就返回当前的节点

代码实现

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* swapPairs(ListNode* head) {//当前节点为空或者下一个节点为空时就返回当前节点if(head==nullptr || head->next==nullptr)return head;//进行节点next指针的修改,使用ret保存当前头节点的指针ListNode* Next=swapPairs(head->next->next),*ret=head->next;head->next->next=head;head->next=Next;//返回retreturn ret;}
};

2.5 Pow(x, n)- 快速幂

50. Pow(x, n) - 力扣(LeetCode)

题目解析 

通过以上的题目描述就可以看出该撒算法题要我们实现的是pow函数,也就是求出指定数的n次幂

算法原理讲解

在这道题当中要实现pow函数,此时我们就要思考应该从什么样的方式去实现,在此如果使用迭代的方式直接将x乘n次,那么按照题目给定的数据范围肯定是会超时的,那么这时候就来想想如何优化。

在此直接得到一个数的n次方很难,那么如果先得到n/2次方再得到n次方不就简单多了吗。例如以上的示例1

 要得到2的10次方就可以通过得到2的5次方,要得到2的5次方就可以先得到2的2次方,最后要得到2的2次方可以先得到2的1次方。这样就可以将要得到一大数转换为从小到大计算的过程。在此就可以发现其实我们每一步进行的过程都是一样的,那么这是就可以使用递归来解决。在此需要要得到的次方是奇数的时候再得到小的次方之后再乘一个x。

接下来就试着来将递归当中的三步分析是什么。

首先是递归当中函数头的设计,此时就要观察重复子问题当中包含哪些。通过以上的步骤图就可以看出函数需要有底数和指数。那么就可以得出函数的参数需要2个,分别是底数和指数。

接下来来分析函数体内该如何实现,也就是只需要观察一个子问题的执行流程。先得到x的n/2的结果是什么再将结果平分就得到x的n次方,当次方数为奇数的时候还要再乘一个x。

最后分析函数的出口

当n为0的时候返回1

代码实现

class Solution {
public:double myPow(double x, int n) {//判断给定的n是否小于0,是的话就需要将得到x的-n次方的结果取倒数return n<0?dfs(1.0/x,-(long long)n):dfs(x,n);}double dfs(double x,long long  n){//当n==0的时候为函数出口if(n==0)return 1;double tmp=dfs(x,n/2);return n%2==0?tmp*tmp:tmp*tmp*x;}};

注:以上dfs内函数参数x的类型设置为long long是因为题目当中n的取值范围是INT_MIN~INT_MAX,如果不使用long long在n为int最小值的时候就会出现溢出

以上就是本篇的全部内容了,接下来我们将继续学习递归、搜索和回溯算法,接下来在下一篇当中我们将会了解到什么是搜索、回溯以及剪枝,未完待续……

相关文章:

递归、搜索和回溯算法《递归》

在之前的优选算法当中我们已经学习了一些基本的算法&#xff0c;那么接下来我们就要来学习算法当中的一大重要章节——递归、搜索和回溯算法&#xff0c;其实也就是大家常常听到的dfs、bfs&#xff1b;其实本质就是递归&#xff0c;在学习搜索、回溯等算法的过程当中我们会先来…...

构建“云中”高并发:12306技术改造的系统性启示

作为曾参与12306余票查询系统高并发升级的技术从业者&#xff0c;笔者注意到公众对于12306底层技术常存在认知盲区。为破解这一迷思&#xff0c;特此分享十年前的架构解密文献&#xff08;该技术之前名叫 gemfire 现已晋升为Apache顶级项目Geode&#xff0c;代码库详见&#xf…...

升级xcode15 报错Error (Xcode): Cycle inside Runner

升级xcode15后报错 Could not build the precompiled application for the device. Error (Xcode): Cycle inside Runner; building could produce unreliable results. This usually can be resolved by moving the shell script phase Thin Binary so that it runs before th…...

gradle-tasks.register(‘classesJar‘, Jar)解析

在使用gradle作为构建工具的android或者java web项目中&#xff0c;我们经常能遇到以下格式 tasks.register(classesJar, Jar) {from "$buildDir/intermediates/javac/release/classes" // 假设使用 release 构建变体 }artifact sourcesJar使用伪代码解释 class Cu…...

深度对比:Objective-C与Swift的RunTime机制与底层原理

1. RunTime简介 RunTime&#xff08;运行时&#xff09;是指程序在运行过程中动态管理类型、对象、方法等的机制。Objective-C 和 Swift 都拥有自己的运行时系统&#xff0c;但设计理念和实现方式有很大不同。理解 RunTime 的底层原理&#xff0c;是掌握 iOS 高级开发的关键。…...

升级Xcode16,flutter项目报错

升级xcode16后发现原来的项目运行不了了&#xff0c;flutter的版本是3.3.1 保错&#xff1a;[ 304 ms] Could not build the precompiled application for the device. [ 16 ms] Error (Xcode): linker command failed with exit code 1 (use -v to see invocation) 1、找到本地…...

MCU内存映射技术详解

MCU内存映射技术详解 1. 引言 内存映射是微控制器(MCU)系统设计中的核心概念&#xff0c;它决定了MCU如何访问和管理内存资源。通过内存映射&#xff0c;处理器可以将物理设备的地址空间映射到自己的逻辑地址空间中&#xff0c;实现对各种硬件资源的统一访问。本文将深入探讨…...

Mac搭建Flutter IOS环境详细指南

目录 1. 准备工作 2. 下载Flutter SDK&#xff1a; 2.1 配置环境 2.2 解决环境报错 zsh:command not found:flutter 2.3、再使用source命令重新加载一下&#xff1a;【source ~/.zshrc】,下次再编辑这个文件就可以直接执行&#xff1a;【open ~/.zshrc】 2.4、执行【flut…...

计算机基础—(九道题)

1. 流程控制题 编写一个程序&#xff0c;输入一个整数&#xff0c;判断它是否是素数&#xff08;质数&#xff09;。 如果是素数&#xff0c;输出Yes&#xff0c;否则输出No。 #include <stdio.h> int main() /* 1. 流程控制题编写一个程序&#xff0c;输入一个整数&…...

蓝桥杯2025年第十六届省赛真题-可分解的正整数

其实只有1不符合要求&#xff0c;因为-1010&#xff0c;作为对称结构&#xff0c;任何数都可以改成加法&#xff0c;比如4-3-2-101234&#xff0c;但因为最小连续的数为3,1恰好在里面&#xff0c;所以1不行。 #include<bits/stdc.h> using namespace std; #define int l…...

Linux虚拟机无法重启网络

这是为什么啊&#xff1f;试了很多种方法都还是失败。 这是本机vmware8的网络配置 这是linux虚拟机的nat配置 这是虚拟机里静态配置的网络 有没有可以答疑解惑一下的&#xff1f;...

8.Android(通过Manifest配置文件传递数据(meta-data))

配置文件 <?xml version"1.0" encoding"utf-8"?> <manifest xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.android.com/tools"><applicationandroid:allowBackup"tr…...

17:00开始面试,17:08就出来了,问的问题有点变态。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到4月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…...

Docker 常用命令(涵盖多个方面)

Docker 命令完整列表&#xff08;表格形式&#xff09; 类别 命令 描述 示例 Docker 服务管理 sudo systemctl start docker 启动 Docker 守护进程 sudo systemctl start docker sudo systemctl stop docker 停止 Docker 守护进程&#xff0c;需先停止所有容…...

前缀树(Trie)(字典树)

做leetcode的时候看到前缀树&#xff0c;听都没听过&#xff0c;后来才知道前缀树就是字典树。之前学过&#xff0c;在OJ项目中用字典树来实现黑白名单限制。浅浅复习一下吧 用字典树来实现黑白名单限制 实现步骤 &#xff08;1&#xff09;定义黑名单 import java.util.Arra…...

word插入APA格式的参考文献

word插入APA格式的参考文献并实现交叉引用 1. 直接手写并采用超链接 2. 使用zotero插入参考文献后采用超链接(前提下载zotero和对应的插件) 1. 直接手写 APA格式生成 1. 在需要插入参考文献的地方手写格式&#xff0c;如下。 2. 生成书签 名字随便填的&#xff0c;&#x…...

n8n部署docker本地化备份和数据持久化和迁移问题

问题总结&#xff1a; 在一开始的操作中&#xff0c;你遇到的主要问题是 Docker 容器内的文件权限导致了文件无法正确写入和修改&#xff0c;尤其是在复制本地备份文件到容器内时。具体问题表现为&#xff1a; 复制文件后&#xff0c;容器内文件权限错误&#xff1a;你使用 do…...

绘制板块层级图

目录 【实验目的】 【实验原理】 【实验环境】 【实验步骤】 【实验总结】 【实验目的】 掌握数据文件读取掌握数据处理的方法实现板块层级图的绘制 【实验原理】 板块层级图&#xff08;treemap&#xff09;是一种基于面积的可视化方式&#xff0c;通过每一个板块&…...

国标云台控制状态

1.基本概念 国标联网系统的信息传输、交换、控制方面的都是通过SIP服务器负责通讯得&#xff0c;SIP负责信令流逐级转发。其中最重要的一部分就是和摄像机进行信令交互。 像安全注册、实时视音频点播、历史视音频的回放等应用的会话控制采用IETFRFC3261规定的Register、Invite等…...

PostgreSQL与MySQL哪个适合做时空数据分析?

PostgreSQL与MySQL的定位与区别 定位差异&#xff1a;功能导向与性能优先 PostgreSQL和MySQL作为两大主流开源数据库&#xff0c;其核心设计理念和适用场景存在显著差异。PostgreSQL定位为 对象-关系型数据库&#xff08;ORDBMS&#xff09; &#xff0c;强调功能完备性与标准…...

uniapp利用生命周期函数实现后台常驻示例

在 Uniapp 中&#xff0c;利用生命周期函数实现“后台常驻”主要是通过监听应用的前后台状态变化&#xff08; onHide 和 onShow &#xff09;&#xff0c;并结合 定时器、后台任务或状态保持逻辑 来实现。但需注意&#xff1a; 纯前端 JS 代码无法突破系统对后台应用的限制&am…...

JAVA设计模式——(八)单例模式

JAVA设计模式——&#xff08;八&#xff09;单例模式 介绍理解实现饿汉式懒汉式 应用 介绍 确保一个类只存在一个实例。 理解 就是一个实例&#xff0c;new出来的一个&#xff0c;很简单。不过单例模式分为了懒汉式和饿汉式&#xff0c;其中也有线程安全的实现方式和线程不…...

【亚马逊云】AWS Wavelength 从理论讲解到实验演练

一、什么是 AWS Wavelength&#xff1f; Wavelength——一种新型的 AWS 基础设施&#xff0c;旨在运行需要低延迟或边缘弹性的工作负载。 AWS Wavelength 将按需计算和存储服务引入通信服务提供商网络&#xff0c;使客户能够构建和部署满足其数据驻留、低延迟和弹性要求的应用…...

Uniapp:vite.config.js全局配置

目录 一、基本概述二、配置自动引入插件一、基本概述 vite.config.js 是一个可选的配置文件,如果项目的根目录中存在这个文件,那么它会被自动加载,一般用于配置 vite 的编译选项 二、配置自动引入插件 在项目命令行终端中执行如下代码 npm install unplugin-auto-import…...

Springboot整合阿里云腾讯云发送短信验证码 可随时切换短信运营商

本文描述了在springboot项目中整合实现对接阿里云 和 腾讯云的短信验证码发送&#xff0c;可通过更改配置文件达到切换短信发送运营商(申请签名、短信模版这些本文不在叙述)。 首先看下大体结构&#xff1a; 一、需要导入的jar <dependency><groupId>com.…...

git 查看用户信息

在 Git 中查看用户信息是一项常见的任务&#xff0c;可以帮助你确认当前仓库的配置或全局的 Git 配置是否正确设置。你可以通过多种方式来查看这些信息。 查看全局用户信息 全局用户信息是应用于所有 Git 仓库的默认设置。要查看全局用户信息&#xff0c;可以使用以下命令&am…...

JAVA基础:Collections 工具类实战指南-从排序到线程安全

在 Java 开发中&#xff0c;集合类几乎贯穿每一个项目&#xff0c;而Collections工具类提供了一系列强大的方法&#xff0c;用于操作和增强集合的功能。无论是排序、查找还是线程安全的封装&#xff0c;Collections工具类都是提升代码效率和质量的重要工具。 一、Collections …...

【计算机视觉】TorchVision 深度解析:从核心功能到实战应用 ——PyTorch 官方计算机视觉库的全面指南

TorchVision 深度解析&#xff1a;从核心功能到实战应用 ——PyTorch 官方计算机视觉库的全面指南 1. TorchVision 项目概览核心模块 2. 实战案例&#xff1a;10 大应用场景详解案例 1&#xff1a;使用预训练 ResNet 进行图像分类代码实现常见问题相关论文 案例 2&#xff1a;加…...

case和字符串操作

使用if选择结构 if [];then elif [];then #注意这个地方,java是else if else ; fi 使用for循环结构 使用for循环&#xff0c;语法结构如下所示&#xff1a; for 变量名 in 值1 值2 值3 #值的数量决定循环任务的次数 do命令序列 done#循环输出1到10 for i in {1..10} #注…...

Golang|外观模式和具体逻辑

最终返回的是Document的切片&#xff0c;然后取得Bytes自己再去做反序列化拿到文档的各种详细信息。 外观模式是一种结构型设计模式&#xff0c;它的目的是为复杂的子系统提供一个统一的高层接口&#xff0c;让外部调用者&#xff08;客户端&#xff09;可以更简单地使用子系统…...

关于kafka

1.为什么需要消息队列 举个经典的例子。 你是一个网购达人&#xff0c;经常在网上购物。快递小哥到了你的小区后&#xff0c;立刻给你打电话说&#xff1a;“你的快递到了&#xff0c;请马上来取。” 但你是一个合格的牛马&#xff0c;在上班&#xff0c;不方便取快递&#…...

OpenCV 图形API(67)图像与通道拼接函数-----水平拼接(横向连接)两个输入矩阵(GMat 类型)函数concatHor()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 该函数用于水平拼接两个 GMat 矩阵&#xff0c;要求输入矩阵的行数必须一致: GMat A { 1, 4,2, 5,3, 6 }; GMat B { 7, 10,8, 11,9, 12 }; GM…...

夜莺 v8.0.0-beta.10 部署

夜莺 v8.0.0-beta.10 部署 1. mariadb-server2. Redis安装3. 下载 n9e-v8.0.0-beta.10-linux-amd64.tar.gz设置 root 用户密码配置文件 配置mariadb的登录密码导入数据库表结构配置为 systemd 启动服务重新加载 systemd配置日志 访问夜莺VictoriaMetrics 时序数据库安装接入数据…...

HTML5好看的水果蔬菜在线商城网站源码系列模板7

文章目录 1.设计来源1.1 主界面1.2 关于我们界面1.3 商城界面1.4 商品信息界面1.5 我的账户界面1.6 联系我们界面 2.效果和源码2.1 动态效果2.2 源代码 源码下载万套模板&#xff0c;程序开发&#xff0c;在线开发&#xff0c;在线沟通 作者&#xff1a;xcLeigh 文章地址&#…...

优化问题中变量分类与作用分析

优化问题中的变量分类与作用 在优化问题中&#xff0c;变量的定义和作用因问题类型和建模需求而异。以下从决策变量、控制变量的区别与联系出发&#xff0c;结合其他相关变量进行系统分析&#xff1a; 1. 决策变量&#xff08;Decision Variables&#xff09; 定义&#xff1a…...

RSS‘25|CMU提出统一空中操作框架:以末端执行器为中心,无人机实现高精度遥操作

导读在科技飞速发展的当下&#xff0c;机器人技术不断拓展其应用边界&#xff0c;空中操作领域成为了研究的热点之一。无人空中操纵器&#xff08;UAMs&#xff09;凭借其在高空复杂任务中的巨大潜力&#xff0c;正逐渐改变着诸如高空设备维护、桥梁检测等传统行业的作业模式&a…...

智能指针之设计模式6

本系列文章探讨了智能指针和设计模式的关系&#xff0c;前面五篇文章介绍的是使用设计模式实现了智能指针的相关特性&#xff0c;比如使用工厂模式控制了智能指针对象的创建&#xff0c;使用代理模式控制了资源对象的销毁。本文介绍一下使用智能指针来帮助我们实现相关的设计模…...

【设计模式】GOF概括

一、创建型模式&#xff08;5种&#xff09; 1. 单例模式 (Singleton) 适用场景&#xff1a;全局唯一实例&#xff08;如配置管理、日志工具&#xff09;。C示例&#xff1a;// 所谓的scott mayer单例模式 class Singleton { public:static Singleton& getInstance() {st…...

深入浅出限流算法(三):追求极致精确的滑动日志

在限流的世界里&#xff0c;精度往往是关键。我们已经讨论过固定窗口&#xff08;简单但有突刺&#xff09;和滑动窗口&#xff08;更平滑但仍有格子边界&#xff09;。如果我们需要更精确的控制&#xff0c;滑动日志 (Sliding Log) 算法便登场了。 核心思想&#xff1a;记录每…...

一文读懂Tomcat应用之 CentOS安装部署Tomcat服务

目录 一、Tomcat概述 (一)、Tomcat安装目录简介 (二)、Tomcat配置文件简介 1、server.xml文件 2、web.xml 3、context.xml 4、tomcat-users.xml 5、logging.properties 二、Tomcat安装部署 (一)、环境规划 (二)、安装JDK 1、下载JDK二进制安装包 2、解压JDK二进制…...

JVM 内存分配策略

引言 在 Java 虚拟机&#xff08;JVM&#xff09;中&#xff0c;内存分配与垃圾回收是影响程序性能的核心机制。内存分配的高效性直接决定了对象创建的速率&#xff0c;而垃圾回收策略则决定了内存的利用率以及系统的稳定性。为了在复杂多变的应用场景中实现高效的内存管理&am…...

轻松上手:使用 Docker Compose 部署 TiDB 的简易指南

作者&#xff1a;ShunWah 在运维管理领域&#xff0c;我拥有多年深厚的专业积累&#xff0c;兼具坚实的理论基础与广泛的实践经验。精通运维自动化流程&#xff0c;对于OceanBase、MySQL等多种数据库的部署与运维&#xff0c;具备从初始部署到后期维护的全链条管理能力。拥有Oc…...

Linux权限管理

权限的概念 在 Linux 系统里&#xff0c;权限管理是系统安全的关键环节。权限管理的核心目的是明确不同用户对文件和目录的操作许可范围&#xff0c;以此来保障系统资源的安全与合理使用。权限管理涉及三种不同的用户角色和三种基本的操作权限。 用户角色 所有者&#xff08…...

Crusader Kings III 王国风云 3(十字军之王 3) [DLC 解锁] [Steam] [Windows SteamOS macOS]

Crusader Kings III 王国风云 3&#xff08;十字军之王 3&#xff09; [DLC 解锁] [Steam] [Windows & SteamOS & macOS] DLC 版本 至最新全部 DLC 后续可能无法及时更新文章&#xff0c;具体最新版本见下载文件说明&#xff1b; DLC 解锁列表&#xff08;仅供参考&am…...

架构风格对比

架构风格深度对比&#xff1a;从管道-过滤器到微内核 &#x1f4dc; 引言 在软件架构设计中&#xff0c;不同的架构风格适用于不同的业务场景。本文将深入解析 7种主流架构风格&#xff0c;包括它们的核心思想、优缺点、适用场景&#xff0c;并通过对比表格和示例帮助您选择最…...

V Rising 夜族崛起 [DLC 解锁] [Steam] [Windows SteamOS]

V Rising 夜族崛起 [DLC 解锁] [Steam] [Windows & SteamOS] 注意 这个符号表示 可打开折叠内容 需要有游戏正版基础本体&#xff0c;安装路径不能带有中文&#xff0c;或其它非常规拉丁字符&#xff1b;仅限用于自建服务器&#xff0c;并禁用 VAC &#xff01;&#xff0…...

HTML标记语言_@拉钩教育

目录 1.文本标签 2.格式化标签 3.图片标签 4.超链接标签 5.表格标签 6表单标签 6.1 6.2 6.3 7.行内框架(超链接内套一个页面) 8.多媒体标签(音/视频) 1.文本标签 2.格式化标签 3.图片标签 4.超链接标签 5.表格标签 6表单标签 6.1 6.2 6.3 7.行内框架(超链接内套一个…...

云原生开发革命:iVX 如何实现 “资源即插即用” 的弹性架构?

云原生技术正以惊人的速度重塑软件开发的版图。短短几年间&#xff0c;它从少数技术先驱的实验性方案&#xff0c;迅速崛起为全球企业数字化转型的核心驱动力。Gartner 预测&#xff0c;到 2026 年&#xff0c;全球 85% 的企业将全面采用云原生技术进行应用开发与部署。云原生架…...

whois为什么有时会返回两个不同的域名状态

前阵子发现一直想注册但被别人注册了的一个域名快要过期了&#xff0c;就想着写个脚本跑在电脑上&#xff0c;每分钟检查一次域名状态&#xff0c;一旦域名被正式删除&#xff0c;就发封邮件通知我&#xff0c;这样就不用频繁手动检查域名状态了。 写脚本时发现一个有趣的现象…...

跨境电商店铺矩阵布局:多账号运营理论到实操全解析

在当今竞争激烈的全球电商市场中&#xff0c;跨境电商店铺矩阵布局已成为卖家脱颖而出的关键策略。本文将深入剖析跨境电商店铺矩阵布局的本质、优势&#xff0c;并提供从理论到实操的全方位指导&#xff0c;助力您在全球市场中开启属于自己的销售新篇章。 一、是什么&#xff…...