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

平衡二叉搜索树模拟实现1-------AVL树(插入,删除,查找)

本章目标

1.AVL树的概念
2.AVL树的模拟实现

1.AVL树的概念

1.AVL树是最先被发明的平衡二叉搜索树,AVL树是一颗空树或者具有以下的性质
它的左右子树都是AVL树,并且左右高度差不超过1,AVL树是一颗高度平衡二叉搜索树,通过高度差去控制平衡
2.为什么高度差是1?
当结点个数为8的情况举例
在这里插入图片描述

因为如果为0的话,条件过于苛刻了,这种情况是永远无法达到左右高度差为0的.
最好的情况下n-1层以上是完全二叉树,但是仍然会多出来一个结点让高度差为1.

3.AVL树得名于它的发明者G.M.Adelson-Velsky和E.M.Landis是两个前苏联的科学家,他们在1962年的论文《Analgorithmfortheorganizationofinformation》中发表了它。
4.AVL树的实现我们在这里引入了一个平衡因子的概念,每一个结点都有平衡因子,在这里我们规定平衡因子的计算为,右子树高度-左子树高度,也就是在这里平衡因子只有三种可能值,-1/0/1.AVL树并不是一定要平衡因子,我们只是在这里选择使用平衡因子这种方式去实现AVL树,我们通过平衡因子去控制每一个结点的高度让这课树变得平衡.
(如上的中每个结点上面的数字,就是平衡因子)
5.AVL树的整体结构是和完全二叉树类似的,所以搜索效率是logn,相对于二叉搜索树是本质的提升
6.在这里引入平衡因子我们一眼就可以看出以下这颗树不是AVL树因为下面这个2的结点左右高度差为2了.
在这里插入图片描述

2.AVL树的模拟实现

因为对于map和set,它们的底层是红黑树,这也是一种平衡二叉搜索树,它们底层的key和Value是用pair封装的,我们这里也使用pair封装,AVL树的实现不只有一种,在这里我们使用三叉链的方式实现,多增加一个parents指针去记忆父节点.在这里还有另一种实现思路是用栈实现.在这里推荐参考殷人昆老师的<<数据结构(用面向对象方法与c++语言描述)>>里面有详细记载用stack去记忆父节点去实现AVL树的方式,我们在这里不过多展开.相对于正常二叉搜索树在这里我们还增加了一个变量去记录平衡因子.
为了泛型编程,我们使用模板去控制数据类型
以下就是AVL树结点的结构

template<class K,class V>
struct AVLTree_Node
{typedef AVLTree_Node<K,V> Node;pair<K, V> _kv;Node* left;Node* right;Node* parents;int pf;AVLTree_Node(const pair<K,V>& data):left(nullptr),right(nullptr),parents(nullptr),_kv(data),pf(0){}
};

2.1插入

对于AVL树的插入过程来说,它只是在二叉搜索树过程中增加了两个部分,更新平衡因子,根据平衡因子进行调整.
因为我们新增一个结点是可能会印象整棵树的高度的,我们要不断更新二叉树中的平衡因子直到达到结束条件,结束条件我们后续会详细分析
对于不平衡的结点我们通过旋转进行调节.旋转的本质是降低高度,且不会影响上一层

2.1.2平衡因子更新规则

在前面我们规定了
1.平衡因子的大小 = 右子树的高度-左子树的高度
2.在这里只有树的高度出现变化才会影响平衡因子
3.我们在左子树进行插入相当于parents的平衡因子–,我们在右子树进行插入的话相当于parents的平衡因子++.
4.parents的平衡因子会决定是否往上更新

2,1.3停止条件

1.如果在更新完平衡因子之后,parents的平衡因子为0的话,我们就停止更新,因为parents在更新前只有两种可能,parents为-1或者1.也就是对于它的左右子树来说是一边高一边低的情况.我们插入结点到parents低的那一边,但对于parents所在的那条子树来说,它的整体高度并没有发生改变.不会影响parents的父节点的平衡因子,更新结束.
在这里插入图片描述

2.如果在更新完平衡因子之后,parents的平衡因子为1或者-1的话,我们就继续更新,因为在没有更新之前parents的平衡因子为0,也就是说它是平衡的,在我们新增一个结点之后parents的高度发生改变,它的改变必然引起parents的parents的结点发生改变.要继续更新
3.如果更新之后parents的结点的高度为2/-2,这也就说明parents之前为一高一低的情况,并且我们插入结点的时候也插入到高的那一边,这样就导致了该AVL不平衡了要进行旋转处理.
在这里插入图片描述

旋转的目的有两个
(1)让parents这棵子树平衡
(2)降低高度,恢复插入前的高度差,旋转之后无需更新,
4.更新到根如果根为-1/1,也结束.
在这里插入图片描述
插入的大概逻辑

bool insert(const pair<K,V>& val)
{//插入if (root == nullptr){root = new Node(val);return true;}Node* cur = root;Node* parents = nullptr;while (cur){if (cur->_kv.first<val.first){parents = cur;cur = cur->right;}else if (cur->_kv.first > val.first){parents = cur;cur = cur->left;}else{return false;}}//链接结点cur = new Node(val);if (val.first<parents->_kv.first){cur->parents = parents;parents->left = cur;}else{cur->parents = parents;parents->right = cur;}//平衡因子while (parents){//调整平衡因子if (cur == parents->left){parents->pf--;}else if(cur==parents->right){parents->pf++;}if (parents->pf == -1 || parents->pf == 1){//更新cur = parents;parents = parents->parents;}else if(parents->pf==0){//结束break;}else if (parents->pf == 2 || parents->pf == -2){//旋转处理break;}else{assert(false);}}return true;
}

在这里,我们因为增加一个parents指针去进行维护父节点,所以在间接时也应该考虑.

2.2旋转

旋转出现时为了解决树出现不平衡的情况,它应该遵守以下规则
1.保持搜索树的规则
2.让不平衡的树变得平衡,降低树的高度.
旋转分为四种:右单旋/左单旋/左右双旋/右左双旋

2.2.1右单旋

在这里插入图片描述
在这里我们有一颗根为10的树,并有抽象为a/b/c三种类型的子树,三者均满足AVL树的要求,10可能时整棵树的根,也可能是局部的根,因为旋转的情况有很多种我们在这里并不会进行枚举,抽象为a/b/c来进行表示,下面也会用抽象的例子举例,不过多解释
右单旋主要的解决的是左边高的那边左边高,我们在a插入一个结点,让10不平衡,因为10的左边过高,所以要让10向右边旋转.
右单旋的核心规则
1.因为b的值是介于5和10之间的,我们把b给10的左边,让10成为5的右边,5成为整棵树的根.这样控制了平衡同时使高度重新回到了h+2.如果10为局部根就不需要继续调整了
2.右单旋出现条件cur的平衡因子为-1&&parents的平衡因子为-2
在这里插入图片描述
右单旋实现代码

void RotateR(Node* parents)
{//保存结点Node* subL = parents->left;Node* subLR = subL->right;//调整顺序parents->left = subLR;if (subLR != nullptr){subLR->parents = parents;}Node* prevparents = parents->parents;subL->right = parents;parents->parents = subL;if (parents == root){root = subL;subL->parents = nullptr;}else{if (prevparents->left == parents){prevparents->left = subL;}else if (prevparents->right == parents){prevparents->right = subL;}else{assert(false);}subL->parents = prevparents;}subL->pf = parents->pf = 0;
}

1.在这里我们要提出几点subLR的结点时三个我们要进行操作的结点中唯一一个可能为空的,我们要进行判断.后面我们去更新parents的时候就可能发生空指针的解引用,
2.如果根为局部根的话,要提前进行保存parents的parents,我们要更新parents的父节点的同时,要判断新的根在原来父结点的左边还是右边
3.更新后的平衡因子parents和subL均平衡所以为0.
4.如果更新的parents为根结点,我们要特殊处理,因为根结点没有父亲,同时修改root

2.2.2左单旋

在这里插入图片描述
左单旋处理的情况是右边高的右边高.因为右边太高,我们要让10向左边旋转,控制平衡,同时使高度回到h+2.
左单选的旋转规则
1.因为b的值是介于10和15之间的,我们让b成为10的左=右边,10成为15的左边,15成为新的根
2.左单选出现的情况是cur的平衡因子为1&&parents的平衡因子2.

void RotateL(Node* parents)
{Node* subR = parents->right;Node* subRL = subR->left;parents->right = subRL;if (subRL != nullptr){subRL->parents = parents;}Node* prevparents = parents->parents;subR->left = parents;parents->parents = subR;if (prevparents == nullptr){root = subR;subR->parents = nullptr;}else{if (prevparents->left == parents){prevparents->left = subR;}else if (prevparents->right == parents){prevparents->right = subR;//dadada}else{assert(false);}subR->parents = prevparents;}parents->pf =0, subR->pf = 0;}

在这里的注意事项与右单旋一致.

2.2.3左右双旋

在这里插入图片描述
在这里插入图片描述
通过以上两张图,我们可以看到,如果我们插入数据如果在b的位置的话,仅仅单旋是解决不了问题的,它会让左边的高的右边高变为右边高的左边高.我们就要通过两次旋转解决.
因为涉及两次旋转,我们要将b展开进行讨论,分为以下三种情况
在这里插入图片描述
在这里插入图片描述
(1)场景1当h>=1的时候,我们插入在e子树使8的平衡因为为-1,5为-1,10为-2,不平衡旋转之后,parents的平衡因子为1,剩下两个均为0.
(2)场景2当h>=1的时候,我们插入到f子树,使8的平衡因子变为1,5为-1,10为-2,不平衡旋转之后,subL的平衡因子为-1,剩下两个均为0.
(3)场景3,当h==0的时候,这个时候为新插入的结点,为新增结点,不断更新之后,旋转不平衡,三者旋转后的平衡因子均为0.
在这里我们以第二种情况进行旋转的举例,本质上就是把8的左右结点分别给了两个其他结点.,其他的旋转是类似的
在这里插入图片描述

void RotateLR(Node* parents)
{Node* subL = parents->left;Node* subLR = subL->right;int pf = subLR->pf;RotateL(parents->left);RotateR(parents);if (pf == 0){subL->pf = 0;subLR->pf = 0;parents->pf = 0;}else if (pf == -1){parents->pf = 1;subL->pf = 0;subLR->pf = 0;}else if (pf == 1){parents->pf = 0;subL->pf = -1;subLR->pf = 0;}else{assert(false);}
}

在这里要注意提前保存subL,和subLR以及subLR的平衡因子,因为进行单旋的时候会更新平衡因子,我们要根据subLR的平衡因子进行调整新的平衡因子.

2.2.4右左双旋

在这里插入图片描述
在这里插入图片描述

跟左右双旋类似,下面我们将a/b/c子树抽象为高度h的AVL子树进行分析,另外我们需要把b子树的细节进⼀步展开为12和左子树高度为h-1的e和f子树,因为我们要对b的父亲15为旋转点进行右单旋,右单旋需要动b树中的右⼦树。b子树中新增结点的位置不同,平衡因子更新的细节也不同,通过观察12的平衡因子不同,这里我们要分三个场景讨论。
(1)场景1,当h>=1的时候,我们插入在e子树的时候,会导致12的平衡因子变为-1,15的平衡因子变为-1,10的平衡因子变为2,导致不平衡需要旋转处理,处理之后,subR的平衡因子变为1,其他为0
(2)场景2,当h>=1的时候,我们插入到f子树的时候,会导致12的平衡因子变为1,15的平衡因子变为-1,10的平衡因子变为2不平衡旋转处理后,parents的平衡因子1变为-1,其他为0
(3)场景3,当h==0的时候,我们插入相当于新增结点,会直接导致不平衡发生旋转,旋转后三者的平衡因子均为0.

void RotateRL(Node* parents)
{Node* subR = parents->right;Node* subRL = subR->left;int pf = subRL->pf;RotateR(parents->right);RotateL(parents);if (pf == 0){subR->pf = 0;subRL->pf = 0;parents->pf = 0;}else if (pf == -1){parents->pf = 0;subRL->pf = 0;subR->pf = -1;}else if(pf == 1){subR->pf = 0;parents->pf = -1;subRL->pf = 0;}else{assert(false);}
}

注意细节是与2.2.3的左右双旋一致的,要提前保存几个结点.

1.3删除

对于删除来说,它的整体逻辑是和二叉搜索树的删除时大差不差的,唯一要注意的时更新平衡因子,以及不平衡时要进行旋转调整.
根据我们所规定的
平衡因子的大小等于 = 右子树的高度-左子树的高度
在这里如果我们在左子树删除结点相当于平衡因子–,在右子树删除结点相当于平衡因子++.
平衡因子的结束的条件也有所不同.
1.当平衡因子在更新完之后为-1或者1我们结束,因为在之前它一定时0,也就是左右高度时均衡的,我们删除操作并没有影响整颗二叉树的高度所以要结束.
2.当更新完平衡因子为0的情况要继续更新,因为更新前它一定是-1/1,对于父节点来说,它的左右高度差为1,符合avl树的要求,但是在我们删除之后,它为0平衡了,但是父节点整体的子树高度要发生变化了,所以要继续更新
3.当为-2/2的时候是不平衡了,我们删除破坏了avl树的结构.但具体调节的情况是和插入一致的.在这里不冗余介绍.

bool erase(const pair<K, V>& val)
{Node* cur = root;Node* parents = nullptr;while (cur){if (cur->_kv.first < val.first){parents = cur;cur = cur->right;}else if (cur->_kv.first > val.first){parents = cur;cur = cur->left;}else{if (cur->left == nullptr){if (cur == root){root = cur->right;}else{if (parents->left == cur){parents->left = cur->right;}else if (parents->right == cur){parents->right = cur->right;}}delete cur;}else if (cur->right == nullptr){if (cur == root){root = cur->left;}else{if (parents->left == cur){parents->left = cur->left;}else if (parents->right == cur){parents->right = cur->left;}}delete cur;}else{Node* pminright = cur;Node* minright = cur->right;while (minright->left){pminright = minright;minright = minright->left;}swap(cur->_kv, minright->_kv);if (pminright->left == minright)pminright->left = minright->right;elsepminright->right = minright->right;delete minright;parents = pminright;}while (parents){if (parents->left == nullptr){parents->pf++;}else if(parents->right==nullptr){parents->pf--;}if (parents->pf == 1 || parents->pf == -1){break;}else if(parents->pf==0){cur = parents;parents = parents->parents;}else if (parents->pf == -2 || parents->pf == 2){if (parents->pf == 2 && cur->pf == 1){RotateL(parents);}else if (parents->pf == -2 && cur->pf == -1){RotateR(parents);}else if (parents->pf == 2 && cur->pf == -1){RotateRL(parents);}else if (parents->pf == -2 && cur->pf == 1){RotateLR(parents);}else{assert(false);}}}return true;}}return false;
}

在这里需要注意的是在左右孩子都有的情况进行删除我们走的并不是parents的逻辑,而是寻找了一个值进行替代,在删除结束后要将pminright的值给parents;

1.4查找

查找是与二叉搜索树一致的,找到就返回当前结点找不到就返回nullptr

Node* find(const pair<K, V>& val)
{Node* cur = root;while (cur){if (cur->_kv.first < val.first){cur = cur->right;}else if (cur->_kv.first > val.first){cur = cur->left;}else{return cur;}}return nullptr;
}

1.5平衡因子检测

我们可以通过递归求高度差相减来求平衡因子是否正确

bool _IsBalanceTree(Node* root)
{// 空树也是AVL树if (nullptr == root)return true;// 计算pRoot结点的平衡因子:即pRoot左右子树的高度差int leftHeight = height(root->left);int rightHeight = height(root->right);int diff = rightHeight - leftHeight;// 如果计算出的平衡因子与pRoot的平衡因子不相等,或者// pRoot平衡因子的绝对值超过1,则一定不是AVL树if (abs(diff) >= 2){cout << root->_kv.first << "高度差异常" << endl;return false;}if (root->pf != diff){cout << root->_kv.first << "平衡因子异常" << endl;return false;}// pRoot的左和右如果都是AVL树,则该树一定是AVL树return _IsBalanceTree(root->left) && _IsBalanceTree(root->right);
}

测试案例

 AVLTree<int, int> t;// 常规的测试用例//int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };// 特殊的带有双旋场景的测试用例
int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };for (auto e : a){//fsfsfsfsf/* if (e == 14){int x = 0;}*/t.insert({ e, e });/*cout << "Insert" << e << "->";cout << t.IsBalanceTree() << endl;*/}t.Inorder();cout << t.IsBalanceTree() << endl;t.erase({3,3});t.erase({ 6,6 });t.Inorder();cout << t.IsBalanceTree() << endl;

1.6其他

在这里还有size,height等函数的实现,但与二叉搜索树的是一致的,同时包括1.5的函数均用类封装提供接口的形式实现具体代码可以参考我的代码仓库
代码参考

相关文章:

平衡二叉搜索树模拟实现1-------AVL树(插入,删除,查找)

本章目标 1.AVL树的概念 2.AVL树的模拟实现 1.AVL树的概念 1.AVL树是最先被发明的平衡二叉搜索树,AVL树是一颗空树或者具有以下的性质 它的左右子树都是AVL树,并且左右高度差不超过1,AVL树是一颗高度平衡二叉搜索树,通过高度差去控制平衡 2.为什么高度差是1? 当结点个数为8…...

运算放大器的主要技术指标

运放&#xff08;运算放大器&#xff09;是一种基础电子器件&#xff0c;具有输入阻抗高、开环放大倍数大、输入端电流小、同相端与反相端电压几乎相等等特点。在选型时&#xff0c;需要考虑技术指标如输入失调电压、输入失调电压漂移、输入失调电流、共模抑制比、压摆率、建立…...

51单片机入门教程——每个音符对应的重装载值

前言 本教程基于B站江协科技课程进行个人学习整理&#xff0c;专为拥有C语言基础的零基础入门51单片机新手设计。既帮助解决因时间差导致的设备迭代调试难题&#xff0c;也助力新手快速掌握51单片机核心知识&#xff0c;实现从C语言理论到单片机实践应用的高效过渡 。...

新一代智能座舱娱乐系统软件架构设计文档

一 文档概述 本文档描述了基于Android系统与多模态大模型融合的新一代智能座舱娱乐系统的软件架构设计。该系统将通过深度学习的个性化适配、多模态感知融合和持续自进化能力&#xff0c;重新定义人车交互体验。 二 整体架构设计 2.1 分层架构视图 系统采用五层垂直架构与三…...

深度优先搜索(DFS)与广度优先搜索(BFS):图与树遍历的两大利器

深度优先搜索&#xff08;DFS&#xff09;与广度优先搜索&#xff08;BFS&#xff09;&#xff1a;图与树遍历的两大利器 在数据结构与算法的世界中&#xff0c;深度优先搜索&#xff08;DFS&#xff09;和广度优先搜索&#xff08;BFS&#xff09;是两种非常经典的遍历算法。…...

比较 TensorFlow 和 PyTorch

TensorFlow和PyTorch是深度学习领域中两个非常流行的开源机器学习框架&#xff0c;下面为你详细介绍。 1. 历史与背景 TensorFlow&#xff1a;由Google开发和维护&#xff0c;于2015年开源。因其强大的生产能力和广泛的工具支持&#xff0c;在工业界得到了广泛应用。PyTorch&…...

jeecg查询指定时间

jeecg查询指定时间 ApiOperation(value"请假表-分页列表查询", notes"请假表-分页列表查询")GetMapping(value "/list")public Result<IPage<MlLeaveRequest>> queryPageList(MlLeaveRequest mlLeaveRequest,RequestParam(name&qu…...

无人机视觉:连接像素与现实世界 —— 像素与GPS坐标双向转换指南

在无人机航拍应用中&#xff0c;一个核心的需求是将图像上的某个点与现实世界中的地理位置精确对应起来。无论是目标跟踪、地图测绘还是农情监测&#xff0c;理解图像像素与其对应的经纬度&#xff08;GPS坐标&#xff09;之间的关系至关重要。本文将详细介绍如何实现单个像素坐…...

php study 网站出现404 - Page Not Found 未找到

最近在用php study搭建本地网站时&#xff0c;出现了404 - Page Not Found 未找到的情况&#xff0c;解决方式如下&#xff1a; 第一种&#xff1a;在wp 后台固定链接设置中修改链接形式 第二种:没有安装伪静态! 小皮面板中 设置--配置文件--编辑你所搭建的网站 在红色框框处…...

互联网大厂Java求职面试:核心技术点深度解析

互联网大厂Java求职面试&#xff1a;核心技术点深度解析 在互联网大厂的Java岗位面试中&#xff0c;技术总监级别的面试官通常会从实际业务场景出发&#xff0c;层层深入地考察候选人的技术能力。本文通过一个严肃专业的技术总监与搞笑但有技术潜力的程序员郑薪苦之间的互动对…...

【Java idea配置】

IntelliJ IDEA创建类时自动生成注释 /** * program: ${PROJECT_NAME} * * since: jdk1.8 * * description: ${description} * * author: ${USER} * * create: ${YEAR}-${MONTH}-${DAY} ${HOUR}:${MINUTE} **/自动导入和自动移除无用导入 idea彩色日志不生效 调试日志输出 在…...

[GESP202503 四级] 二阶矩阵c++

题目描述 小 A 有一个 n 行 m 列的矩阵 A。 小 A 认为一个 22 的矩阵 D 是好的&#xff0c;当且仅当 。其中 表示矩阵 D 的第 i 行第 j 列的元素。 小 A 想知道 A 中有多少个好的子矩阵。 输入 第一行&#xff0c;两个正整数 n,m。 接下来 n 行&#xff0c;每行 m 个整数…...

PyQt5基本介绍

PyQt5是基于Digia公司强大图形框架Qt5的python接口&#xff0c;由一组python模块构成。是一个用于创建桌面应用程序的Python库&#xff0c;它是Qt图形用户界面工具包的Python绑定。 Qt是一个跨平台的C库&#xff0c;提供了一套丰富的工具和功能&#xff0c;用于开发图形用户界…...

Spring AI 实战:第十章、Spring AI RAG之博学多才

引言:从“博闻强记”到“博学多才” 在人工智能的发展历程中,大语言模型(LLM)已经展现了惊人的“博闻强记”能力——它们能写诗、编码、解答常识问题,甚至模拟人类对话。然而,当面对专业领域知识或实时更新的信息时,这些模型往往会暴露其局限性:要么“一本正经地胡说八…...

Runnable 组件生命周期监听器与使用场景

Runnable 生命周期监听器 1.1 监听机制演进 在 LangChain 框架中&#xff0c;Runnable 组件提供两种监控方案&#xff1a; ​​传统模式​​&#xff1a;通过 config callbacks 参数传递回调配置​​增强模式​​&#xff1a;使用 with_listeners() 方法实现生命周期订阅 …...

五、shell脚本--函数与脚本结构:搭积木,让脚本更有条理

随着我们的脚本越来越长、越来越复杂&#xff0c;直接把所有命令堆在一起会变得难以阅读和维护。这时候&#xff0c;函数 (Function) 就派上大用场了&#xff01; 函数就像一个可以重复使用的代码块&#xff0c;你可以给它起个名字&#xff0c;然后在脚本的任何地方通过名字来…...

单调栈与单调队列(c艹)、可视化Qt?

单调栈和单调队列的区别在于 ChatGLM 单调栈和单调队列都是数据结构中用于处理序列问题的工具&#xff0c;它们在处理问题时具有不同的特性和应用场景。以下是单调栈和单调队列的主要区别&#xff1a; 定义&#xff1a; 单调栈&#xff1a;是一种特殊的栈&#xff0c;其中的元…...

哈夫曼树和哈夫曼编码

哈夫曼编码一般用来对字符串进行编码格式的表示。其中要克服的最大问题&#xff0c;莫过于就是一串由0或者1组成的编码&#xff0c;你无法区分哪些01组成的编码部分是属于哪些字符的&#xff0c;因此哈夫曼编码的出现解决了这个问题。 在介绍哈夫曼编码之前&#xff0c;先介绍…...

基于 AI 的人像修复与编辑技术:CompleteMe 系统的研究与应用

概述 加利福尼亚大学默塞德分校与 Adobe 的新合作在人像补全领域取得了突破性进展——人像补全是一项备受关注的任务&#xff0c;旨在“揭示”人像中被遮挡或隐藏的部分&#xff0c;可用于虚拟试穿、动画制作和照片编辑等场景。 除了修复损坏的图像或根据用户意愿更改图像外&a…...

spring 使用FactoryBean注入bean

spring 使用FactoryBean注入bean 1、介绍 ​ 通常是ApplicationContext&#xff0c;就是IOC容器&#xff0c;ApplicationContext是BeanFactory的实现类&#xff0c;是spring最核心的接口。用getBean来加载bean。BeanFactory相当于是IOC的基础类。而FactoryBean是另一个东西&a…...

AI 编程日报 · 2025 年 5 月 04 日|GitHub Copilot Agent 模式发布,Ultralytics 优化训练效率

1、OpenAI 确认 GPT-4o“谄媚”个性更新已完全回滚 OpenAI 官方已确认&#xff0c;先前推送的一项旨在改进 GPT-4o 模型个性的更新已被完全撤销。该更新最初目标是提升模型的智能与个性&#xff0c;使其交互更直观有效&#xff0c;但实际效果却导致模型表现出过度“谄媚”和“…...

C++ STL简介:构建高效程序的基石

0. 引言 在现代软件开发领域&#xff0c;C语言凭借其强大的性能和灵活性占据着重要地位。而C标准模板库&#xff08;Standard Template Library&#xff0c;简称STL&#xff09;作为C标准库的核心组件&#xff0c;更是开发者手中不可或缺的利器。它犹如一座知识宝库&#xff0…...

大模型(LLMs)RAG 版面分析——文本分块面

大模型&#xff08;LLMs&#xff09;RAG 版面分析——文本分块面 一、为什么需要对文本分块&#xff1f; 二、能不能介绍一下常见的文本分块方法&#xff1f; 2.1 一般的文本分块方法 2.2 正则拆分的文本分块方法 2.3 Spacy Text Splitter 方法 2.4 基于 langchain 的 Cha…...

系统思考:核心价值与竞争力

最近&#xff0c;设计师的小伙伴跟我提到&#xff0c;行业内竞争越来越激烈&#xff0c;大家都开始拼命降价。但从系统思考的角度来看&#xff0c;我想说一句话&#xff1a;“人多的地方&#xff0c;不要去。” 为什么这么说&#xff1f;在竞争愈发激烈的环境中&#xff0c;我…...

【RocketMQ Broker 相关源码】- broker 启动源码(2)

文章目录 1. 前言2. 创建 DefaultMessageStore3. DefaultMessageStore#load3.1 CommitLog#load3.2 loadConsumeQueue 加载 ConsumeQueue 文件3.3 创建 StoreCheckpoint3.4 indexService.load 加载 IndexFile 文件3.5 recover 文件恢复3.6 延时消息服务加载 4. registerProcesso…...

mysql中int(1) 和 int(10) 有什么区别?

困惑 最近遇到个问题&#xff0c;有个表的要加个user_id字段&#xff0c;user_id字段可能很大&#xff0c;于是我提mysql工单​​alter table xxx ADD user_id int(1)​​。领导看到我的sql工单&#xff0c;于是说&#xff1a;这int(1)怕是不够用吧&#xff0c;接下来是一通解…...

jetson orin nano super AI模型部署之路(八)tensorrt C++ api介绍

我们基于tensorrt-cpp-api这个仓库介绍。这个仓库的代码是一个非常不错的tensorrt的cpp api实现&#xff0c;可基于此开发自己的项目。 我们从src/main.cpp开始按顺序说明。 一、首先是声明我们创建tensorrt model的参数。 // Specify our GPU inference configuration optio…...

渗透测试中扫描成熟CMS目录的意义与技术实践

在渗透测试领域&#xff0c;面对一个成熟且“看似安全”的CMS&#xff08;如WordPress、Drupal&#xff09;&#xff0c;许多初级测试者常陷入误区&#xff1a;认为核心代码经过严格审计的CMS无需深入排查。然而&#xff0c;目录扫描&#xff08;Directory Bruteforcing&#x…...

数字信号处理学习笔记--Chapter 1 离散时间信号与系统

1 离散时间信号与系统 包含以下内容&#xff1a; &#xff08;1&#xff09;离散时间信号--序列 &#xff08;2&#xff09;离散时间系统 &#xff08;3&#xff09;常系数线性差分方程 &#xff08;4&#xff09;连续时间信号的抽样 2 离散时间信号--序列 为了便于计算机对信号…...

LeetCode 热题 100 994. 腐烂的橘子

LeetCode 热题 100 | 994. 腐烂的橘子 大家好&#xff0c;今天我们来解决一道经典的算法题——腐烂的橘子。这道题在LeetCode上被标记为中等难度&#xff0c;要求我们计算网格中所有新鲜橘子腐烂所需的最小分钟数&#xff0c;或者返回不可能的情况。下面我将详细讲解解题思路&…...

软考-软件设计师中级备考 11、计算机网络

1、计算机网络的分类 按分布范围分类 局域网&#xff08;LAN&#xff09;&#xff1a;覆盖范围通常在几百米到几千米以内&#xff0c;一般用于连接一个建筑物内或一个园区内的计算机设备&#xff0c;如学校的校园网、企业的办公楼网络等。其特点是传输速率高、延迟低、误码率低…...

NHANES指标推荐:LC9

文章题目&#xff1a;Association between lifes crucial 9 and kidney stones: a population-based study DOI&#xff1a;10.3389/fmed.2025.1558628 中文标题&#xff1a;生命的关键 9 与肾结石之间的关联&#xff1a;一项基于人群的研究 发表杂志&#xff1a;Front Med 影响…...

使用 Azure DevSecOps 和 AIOps 构建可扩展且安全的多区域金融科技 SaaS 平台

引言 金融科技行业有一个显著特点&#xff1a;客户期望能够随时随地即时访问其财务数据&#xff0c;并且对宕机零容忍。即使是短暂的中断也会损害用户的信心和忠诚度。与此同时&#xff0c;对数据泄露的担忧已将安全提升到整个行业的首要地位。 在本文中&#xff0c;我们将探…...

原子单位制换算表

速度 0.12.1880.24.3760.36.5640.48.7520.510.940.613.1280.715.3160.817.5040.919.692121.881.532.82243.762.554.7...

【C++重载操作符与转换】下标操作符

目录 一、下标操作符重载基础 1.1 什么是下标操作符重载 1.2 默认行为与需求 1.3 基本语法 二、下标操作符的核心实现策略 2.1 基础实现&#xff1a;一维数组模拟 2.2 多维数组实现&#xff1a;矩阵类示例 三、下标操作符的高级用法 3.1 自定义索引类型&#xff1a;字…...

文章记单词 | 第62篇(六级)

一&#xff0c;单词释义 noon [nuːn] n. 中午&#xff0c;正午clothes [kləʊz] n. 衣服&#xff0c;衣物reward [rɪˈwɔːd] n. 报酬&#xff0c;奖赏&#xff1b;vt. 奖励&#xff0c;奖赏newly [ˈnjuːli] adv. 最近&#xff0c;新近&#xff1b;以新的方式premier [ˈ…...

《CUDA:解构GPU计算的暴力美学与工程哲学》

《CUDA:解构GPU计算的暴力美学与工程哲学》 ​ CUDA 的诞生,宛如在 GPU 发展史上划下了一道分水岭。它不仅赋予了 GPU 走出图形处理的 “舒适区”,投身通用计算的 “新战场” 的能力,更是一场对计算资源分配与利用逻辑的彻底重构。在这场技术革命中,CUDA 以它犀利的架构设…...

Linux ACPI - ACPI系统描述表架构(2)

ACPI系统描述表架构 1.概要 ACPI defines a hardware register interface that an ACPI-compatible OS uses to control core power management features of a machine, as described in ACPI Hardware Specification ACPI also provides an abstract interface for controlli…...

实时在线状态

以下是一个完整的 OnlineUsers 类实现&#xff0c;包含线程安全的在线用户管理功能&#xff1a; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors;/*** 在线用户管理器&#xff08;线程安全&#xff09;* 功能&#…...

《算法导论(第4版)》阅读笔记:p6-p6

《算法导论(第4版)》学习第 4 天&#xff0c;p6-p6 总结&#xff0c;总计 1 页。 一、技术总结 无。 二、英语总结(生词&#xff1a;1) 1. disposal (1)dispose: dis-(“aprt”) ponere(“to put, place”) vt. dispose literally means “to put apart(to separate sth…...

录播课制作技术指南

1.技术版本选择策略 优先采用长期支持版本作为课程开发基础&#xff0c;此类版本在企业级应用中普及度高且稳定性强。技术选型直接影响课程生命周期&#xff0c;稳定的底层框架可降低后续维护成本&#xff0c;避免因技术迭代导致教学内容快速过时。建议定期查看技术社区官方公告…...

【2025软考高级架构师】——知识脑图总结

摘要 本文是一份关于 2025 年软考高级架构师的知识脑图总结。整体涵盖系统工程与信息系统基础、软件工程、项目管理等众多板块&#xff0c;每个板块又细分诸多知识点&#xff0c;如系统工程部分提及系统工程方法、信息系统生命周期等内容&#xff0c;旨在为备考人员提供系统全…...

Allegro23.1新功能之如何设置高压爬电间距规则操作指导

Allegro23.1新功能之如何设置高压爬电间距规则操作指导 Allegro23.1升级到了23.1之后,新增了一个设置高压爬电间距的规则 如下图,不满足爬电间距要求,以DRC的形式报出来了...

**电商推荐系统设计思路**

互联网大厂Java面试实录&#xff1a;马小帅的生死时速 第一轮提问 面试官&#xff08;严肃地&#xff09;&#xff1a;马小帅&#xff0c;请你先简单介绍一下你过往的项目经验&#xff0c;特别是你在项目中使用的技术栈。 马小帅&#xff08;紧张地搓手&#xff09;&#xff…...

BC19 反向输出一个四位数

题目&#xff1a;BC19 反向输出一个四位数 描述 将一个四位数&#xff0c;反向输出。&#xff08;有前导零的时候保留前导零&#xff09; 输入描述&#xff1a; 一行&#xff0c;输入一个整数n&#xff08;1000 < n < 9999&#xff09;。 输出描述&#xff1a; 针对每组…...

【前端】【面试】在 Vue-React 的迁移重构工作中,从状态管理角度来看,Vuex 迁移到 Redux 最大的挑战是什么,你是怎么应对的?

在从 Vue&#xff08;Vuex&#xff09;迁移到 React&#xff08;Redux&#xff09;时&#xff0c;状态管理无疑是重构中最具挑战性的部分之一。两者虽本质上都实现了全局状态集中式管理&#xff0c;但在思想、结构与实现方式上存在显著差异。 Vuex 到 Redux 状态管理迁移的挑战…...

ActiveMQ 与其他 MQ 的对比分析:Kafka/RocketMQ 的选型参考(一)

消息队列简介 在当今的分布式系统架构中&#xff0c;消息队列&#xff08;Message Queue&#xff0c;MQ&#xff09;扮演着举足轻重的角色&#xff0c;已然成为构建高可用、高性能系统不可或缺的组件。消息队列本质上是一种异步通信的中间件&#xff0c;它允许不同的应用程序或…...

OPENGLPG第九版学习 -视口变换、裁减、剪切与反馈

文章目录 5.1 观察视图5.1.1 视图模型—相机模型OpenGL的整个处理过程中所用到的坐标系统&#xff1a;视锥体视锥体的剪切 5.1.2 视图模型--正交视图模型 5.2 用户变换5.2.1 矩阵乘法的回顾5.2.2 齐次坐标5.2.3 线性变换与矩阵SRT透视投影正交投影 5.2.4 法线变换逐像素计算法向…...

大连理工大学选修课——图形学:第一章 图形学概述

第一章 图形学概述 计算机图形学及其研究内容 计算机图形学&#xff1a;用数学算法将二维或三维图形转化为计算机显示器的格栅形式的科学。 图形 计算机图形学的研究对象为图形广义来说&#xff0c;能在人的视觉系统形成视觉印象的客观对象都可称为图形。 既包括了各种几何…...

雅思听力--75个重点单词/词组

文章目录 1. in + 一段时间2. struggle with + doing sth.3. due to + n. / doing sth.4. all kinds of + n.5. supply6. get sb. down7. sth. be a hit8. ups and downs1. in + 一段时间 “in ten minutes”表示“10分钟内”,“in + 一段时间”表示“在一段时间之内”。 You…...