【C++】学习笔记——AVL树

文章目录

  • 十六、AVL树
    • 1. AVL树的概念
    • 2. AVL树节点的定义
    • 3. AVL树的插入
    • 4. AVL树的旋转
    • 5. AVL树的验证
    • 6. 完整代码+测试
    • 7. AVL树的性能
  • 未完待续


十六、AVL树

1. AVL树的概念

二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下。因此,两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年发明了一种解决上述问题的方法:
当向二叉搜索树中插入新结点后,如果能保证 每个结点的左右子树高度之差的绝对值不超过1 (需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。
在这里插入图片描述
上面这两个二叉树都不是AVL树。

AVL树的左右子树都是AVL树,左右子树高度之差(简称平衡因子) 的绝对值不超过1。平衡因子 = 右子树高度 - 左子树高度

这才是AVL树。AVL树是一个高度平衡二叉搜索树。
在这里插入图片描述

2. AVL树节点的定义

// AVLTree 节点
template<class K, class V>
struct AVLTreeNode
{// 指向左孩子的指针AVLTreeNode* _left;// 指向右孩子的指针AVLTreeNode* _right;// 指向父节点的指针AVLTreeNode* _parent;// 平衡因子int _bf;// 存储的Key-Value结构数据std::pair<K, V> _kv;// 节点的构造函数AVLTreeNode(const pair<K, V>& kv):_left(nullptr),_right(nullptr),_parent(nullptr),_bf(0),_kv(kv){}
};

3. AVL树的插入

由于AVL树一颗二叉搜索树,所以我们插入的时候需要根据二叉搜索树的插入方式插入新节点(比父节点小就往左走,比父节点大就往右走,直到找到空节点插入该新节点), 但是!相比于二叉搜索树,AVL树还有一套自己的规则,他要保证高度需要平衡,所以当我们插入新节点的时候,必须要判断插入后的节点是否会破坏AVL树的平衡。如何判断AVL树是否平衡?保证平衡因子只在 -1 0 1 三个数就行了。
在这里插入图片描述
假设我们要插入的新节点在 6号 节点的左侧。由于新节点插入的位置一定是一个 空树 ,所以 新节点的插入导致该侧树的高度 + 1 ,则需要更新一下父节点的平衡因子。

新节点插入在父节点的左侧 —> 父节点的平衡因子 - 1
新节点插入在父节点的右侧 —> 父节点的平衡因子 + 1

重点来了!插入新节点后,难道它就只影响父节点的平衡因子吗? 它影响的是包含它的所有树! 即它的祖先节点。我们不能只仅仅修正父节点的平衡因子。我们还需要逐渐向上修正,直到不需要修正为止。
平衡因子的修正有3种情况:
①修正后变成 0 。不管是从-1变成0还是从1变成0,只要是0,说明左右子树高度相等,并且整体树的高度并没有增加,如果以该节点为根节点的树高度并没有增加,那么对于该节点父节点的平衡因子就没有修正的必要。
①修正后变成 1 或 -1 。同理,父节点肯定是从0变过来的,树的高度发生了变化,则父节点的父节点就仍需要修正平衡因子。
①修正后变成 -2 或 2 。由于平衡因子只能是 -1 ,0 ,1 。所以说明此时的树已经不是AVL树了,我们需要对树进行调整来使其恢复成AVL树。调整方法为 旋转
插入操作代码

bool Insert(const std::pair<K, V>& kv)
{// 空树则创建根节点if (_root == nullptr){_root = new Node(kv);return true;}Node* parent = nullptr;Node* cur = _root;// 找到新节点应该插入的位置while (cur){// 比父节点小, 往左子树找if (kv.first < cur->_kv.first){parent = cur;cur = cur->_left;}// 比父节点大, 往右子树找else if (kv.first > cur->_kv.first){parent = cur;cur = cur->_right;}else{// 已经存在该值, 插入失败return false;}}cur = new Node(kv);// 父节点指向新节点if (kv.first < parent->_kv.first)parent->_left = cur;elseparent->_right = cur;// 新节点指向父节点cur->_parent = parent;// 修正祖先的平衡因子while (parent){// 在树的左子树里插入了新节点 父节点平衡因子减1if (cur == parent->_left)--parent->_bf;// 在树的右子树里插入了新节点 父节点平衡因子加1else++parent->_bf;// 判断修正后的平衡因子是否符合要求if (parent->_bf == 0) break;else if (parent->_bf == 1 || parent->_bf == -1){cur = parent;parent = parent->_parent;}// 该树已经不满足AVL树的性质else if (parent->_bf == 2 || parent->_bf == -2){// 旋转操作break;}// 其他异常情况else assert(false);}// 插入成功return true;
}

在这里插入图片描述
注意,旋转后满足条件,需要退出循环。

4. AVL树的旋转

如果在一棵原本是平衡的AVL树中插入一个新节点,可能会造成不平衡,此时必须调整树的结构,使之平衡化。根据节点插入位置的不同,AVL树的旋转分为四种:
①左子树高度较高,新节点插入在左子树的左侧 — 左左:使用右单旋。
在这里插入图片描述
其中 a,b,c 为子树,h为树的高度。我们需要 将左子树的右子树修改成 60 节点的左孩子,再把 60 节点修改为 30 节点的右孩子, 30 节点则替代原本的 60 节点的位置。如此修正后,AVL树重新平衡,并且 30 节点和 60 节点的平衡因子都会变成 0。
一定要注意的是 :这里的 h 可能为0!必须要判断 b 子树存不存在!
右单旋代码

// 左左 --- 右单旋
void RotateR(Node* parent)
{// 父节点的左孩子Node* subL = parent->_left;// 父节点的左孩子的右孩子Node* subLR = subL->_right;// 父节点的父节点Node* ppnode = parent->_parent;// 修改父节点的指向parent->_left = subLR;parent->_parent = subL;// 修改父节点的左孩子的指向subL->_right = parent;subL->_parent = ppnode;// 如果父节点的左孩子的右孩子存在,则修改其指向if (subLR)subLR->_parent = parent;// 修改父节点的父节点的指向if (parent == _root)_root = subL;else if (parent == ppnode->_left)ppnode->_left = subL;elseppnode->_right = subL;// 修正后父节点和父节点的左孩子的平衡因子都会变成 0parent->_bf = 0;subL->_bf = 0;
}

②右子树高度较高,新节点插入在右子树的右侧 — 右右:使用左单旋。
在这里插入图片描述
右单旋 同理,只是左右方向相反。
左单旋代码

// 右右 --- 左单旋
void RotateL(Node* parent)
{// 父节点的右孩子Node* subR = parent->_right;// 父节点的右孩子的左孩子Node* subRL = subR->_left;// 父节点的父节点Node* ppnode = parent->_parent;// 修改父节点的指向parent->_right = subRL;parent->_parent = subR;// 修改父节点的右孩子的指向subR->_left = parent;subR->_parent = ppnode;// 如果父节点的右孩子的左孩子存在,则修改其指向if (subRL)subRL->_parent = parent;// 修改父节点的父节点的指向if (parent == _root)_root = subR;else if (parent == ppnode->_left)ppnode->_left = subR;elseppnode->_right = subR;// 修正后父节点和父节点的右孩子的平衡因子都会变成 0parent->_bf = 0;subR->_bf = 0;
}

①左子树高度较高,新节点插入在左子树的右侧 — 左右:先左单旋再右单旋。
对于左单旋和右单旋,我们已经差不多能够理解了,但是在这种情况下,单纯使用左右单旋已经无法恢复平衡了,但是我们可以使用 双旋 ,先旋转一次使其符合单旋情况。
在这里插入图片描述
使用两次旋转就能使其恢复AVL树的性质,所以说我们只需要调用两次单旋函数就可以了吗?非也,虽然树的结构对了,但是我们并没有修正平衡因子。我们可以观察得到:60 节点最终成为了这颗子树的根节点,60 节点的左孩子成为了 30 节点的右孩子, 60 节点的右孩子成为了 90 节点的左孩子。
如果 60 节点的平衡因子在没旋转前是 0,则说明 60 节点就是最新插入的节点。那么 a,b,c,d子树都不存在 所以 30 节点、 60 节点、 90 节点的平衡因子都是 0。
如果 60 节点的平衡因子在没旋转前是 -1,则说明新节点插入到了 60 节点的左子树中。所以最后 c 子树将会比 d 子树高度小1,所以 30 节点和 60 节点的平衡因子都是 0, 90 节点的平衡因子是 1。
如果 60 节点的平衡因子在没旋转前是 1,由上可知, 30 节点的平衡因子是 -1,60 节点和 90 节点的平衡因子都是 0。
先左单旋再右单旋代码

// 左右 --- 先左后右旋
void RotateLR(Node* parent)
{// 父节点的左孩子Node* subL = parent->_left;// 父节点的左孩子的右孩子Node* subLR = subL->_right;// 记录父节点的左孩子的右孩子(新插入的节点的子树)的平衡因子int bf = subLR->_bf;// 左单旋RotateL(subL);// 右单旋RotateR(parent);// 修正平衡因子subLR->_bf = 0;if (bf == 0){parent->_bf = 0;subL->_bf = 0;}else if (bf == 1){parent->_bf = 0;subL->_bf = -1;}else if (bf == -1){parent->_bf = 1;subL->_bf = 0;}
}

④右子树高度较高,新节点插入在右子树的左侧 — 右左:先右单旋再左单旋。
可以参考③先左旋再右旋。
在这里插入图片描述

先右单旋再左单旋代码

// 右左 --- 先右后左旋
void RotateRL(Node* parent)
{// 父节点的右孩子Node* subR = parent->_right;// 父节点的右孩子的左孩子Node* subRL = subR->_left;// 记录父节点的右孩子的左孩子(新插入的节点的子树)的平衡因子int bf = subRL->_bf;// 右单旋RotateR(subR);// 左单旋RotateL(parent);// 修正平衡因子subRL->_bf = 0;if (bf == 0){parent->_bf = 0;subR->_bf = 0;}else if (bf == 1){parent->_bf = -1;subR->_bf = 0;}else if (bf == -1){parent->_bf = 0;subR->_bf = 1;}
}

5. AVL树的验证

AVL树是在二叉搜索树的基础上加入了平衡性的限制,因此要验证AVL树,可以分两步:① 验证其为二叉搜索树。如果中序遍历可得到一个有序的序列,就说明为二叉搜索树。②验证其为平衡树。每个节点子树高度差的绝对值不超过1,判断节点的平衡因子是否计算正确。
中序遍历

void _InOrder(Node* root)
{if (root == nullptr)return;_InOrder(root->_left);std::cout << root->_kv.first << "[" << root->_kv.second << "]" << std::endl;_InOrder(root->_right);
}void InOrder()
{_InOrder(_root);
}

判断树是否平衡&&计算平衡因子是否异常

bool _IsBalance(Node* root, int& height)
{if (root == nullptr){height = 0;return true;}int HeightLeft = 0, HeightRight = 0;// 左右子树有一个不满足就返回falseif (!_IsBalance(root->_left, HeightLeft) || !_IsBalance(root->_right, HeightRight))return false;// 高度不平衡if (std::abs(HeightLeft - HeightRight) > 1){std::cout << root->_kv.first << "该树不平衡" << std::endl;return false;}// 平衡因子计算错误if (HeightRight - HeightLeft != root->_bf){std::cout << root->_kv.first << "平衡因子异常" << std::endl;   return false;}// 返回该子树的高度height = std::max(HeightLeft, HeightRight) + 1;return true;
}bool IsBalance()
{int height = 0;return _IsBalance(_root, height);
}int _Height(Node* root)
{if (root == nullptr)return 0;return std::max(Height(root->_left), Height(root->_right)) + 1;
}int Height()
{return _Height(_root);
}

6. 完整代码+测试

AVLTree.h

#pragma once#include <utility>
#include <cassert>
#include <iostream>template<class K, class V>
struct AVLTreeNode
{AVLTreeNode* _left;AVLTreeNode* _right;AVLTreeNode* _parent;// 平衡因子int _bf;std::pair<K, V> _kv;AVLTreeNode(const std::pair<K, V>& kv):_left(nullptr), _right(nullptr), _parent(nullptr), _bf(0), _kv(kv){}
};template<class K, class V>
class AVLTree
{typedef AVLTreeNode<K, V> Node;
public:bool Insert(const std::pair<K, V>& kv){// 空树则创建根节点if (_root == nullptr){_root = new Node(kv);return true;}Node* parent = nullptr;Node* cur = _root;// 找到新节点应该插入的位置while (cur){// 比父节点小, 往左子树找if (kv.first < cur->_kv.first){parent = cur;cur = cur->_left;}// 比父节点大, 往右子树找else if (kv.first > cur->_kv.first){parent = cur;cur = cur->_right;}else{// 已经存在该值, 插入失败return false;}}cur = new Node(kv);// 父节点指向新节点if (kv.first < parent->_kv.first)parent->_left = cur;elseparent->_right = cur;// 新节点指向父节点cur->_parent = parent;// 修正祖先的平衡因子while (parent){// 在树的左子树里插入了新节点 父节点平衡因子减1if (cur == parent->_left)--parent->_bf;// 在树的右子树里插入了新节点 父节点平衡因子加1else++parent->_bf;// 判断修正后的平衡因子是否符合要求if (parent->_bf == 0) break;else if (parent->_bf == 1 || parent->_bf == -1){cur = parent;parent = parent->_parent;}// 该树已经不满足AVL树的性质else if (parent->_bf == 2 || parent->_bf == -2){// 旋转操作if (parent->_bf == -2 && cur->_bf == -1)RotateR(parent);else if (parent->_bf == 2 && cur->_bf == 1)RotateL(parent);else if (parent->_bf == -2 && cur->_bf == 1)RotateLR(parent);else if (parent->_bf == 2 && cur->_bf == -1)RotateRL(parent);break;}// 其他异常情况else assert(false);}// 插入成功return true;}// 左左 --- 右单旋void RotateR(Node* parent){// 父节点的左孩子Node* subL = parent->_left;// 父节点的左孩子的右孩子Node* subLR = subL->_right;// 父节点的父节点Node* ppnode = parent->_parent;// 修改父节点的指向parent->_left = subLR;parent->_parent = subL;// 修改父节点的左孩子的指向subL->_right = parent;subL->_parent = ppnode;// 如果父节点的左孩子的右孩子存在,则修改其指向if (subLR)subLR->_parent = parent;// 修改父节点的父节点的指向if (parent == _root)_root = subL;else if (parent == ppnode->_left)ppnode->_left = subL;elseppnode->_right = subL;// 修正后父节点和父节点的左孩子的平衡因子都会变成 0parent->_bf = 0;subL->_bf = 0;}// 右右 --- 左单旋void RotateL(Node* parent){// 父节点的右孩子Node* subR = parent->_right;// 父节点的右孩子的左孩子Node* subRL = subR->_left;// 父节点的父节点Node* ppnode = parent->_parent;// 修改父节点的指向parent->_right = subRL;parent->_parent = subR;// 修改父节点的右孩子的指向subR->_left = parent;subR->_parent = ppnode;// 如果父节点的右孩子的左孩子存在,则修改其指向if (subRL)subRL->_parent = parent;// 修改父节点的父节点的指向if (parent == _root)_root = subR;else if (parent == ppnode->_left)ppnode->_left = subR;elseppnode->_right = subR;// 修正后父节点和父节点的右孩子的平衡因子都会变成 0parent->_bf = 0;subR->_bf = 0;}// 左右 --- 先左后右旋void RotateLR(Node* parent){// 父节点的左孩子Node* subL = parent->_left;// 父节点的左孩子的右孩子Node* subLR = subL->_right;// 记录父节点的左孩子的右孩子(新插入的节点的子树)的平衡因子int bf = subLR->_bf;// 左单旋RotateL(subL);// 右单旋RotateR(parent);// 修正平衡因子subLR->_bf = 0;if (bf == 0){parent->_bf = 0;subL->_bf = 0;}else if (bf == 1){parent->_bf = 0;subL->_bf = -1;}else if (bf == -1){parent->_bf = 1;subL->_bf = 0;}}// 右左 --- 先右后左旋void RotateRL(Node* parent){// 父节点的右孩子Node* subR = parent->_right;// 父节点的右孩子的左孩子Node* subRL = subR->_left;// 记录父节点的右孩子的左孩子(新插入的节点的子树)的平衡因子int bf = subRL->_bf;// 右单旋RotateR(subR);// 左单旋RotateL(parent);// 修正平衡因子subRL->_bf = 0;if (bf == 0){parent->_bf = 0;subR->_bf = 0;}else if (bf == 1){parent->_bf = -1;subR->_bf = 0;}else if (bf == -1){parent->_bf = 0;subR->_bf = 1;}}void _InOrder(Node* root){if (root == nullptr)return;_InOrder(root->_left);std::cout << root->_kv.first << "[" << root->_kv.second << "]" << std::endl;_InOrder(root->_right);}   void InOrder(){_InOrder(_root);}bool _IsBalance(Node* root, int& height){if (root == nullptr){height = 0;return true;}int HeightLeft = 0, HeightRight = 0;if (!_IsBalance(root->_left, HeightLeft) || !_IsBalance(root->_right, HeightRight))return false;if (std::abs(HeightLeft - HeightRight) > 1){std::cout << root->_kv.first << "该树不平衡" << std::endl;return false;}if (HeightRight - HeightLeft != root->_bf){std::cout << root->_kv.first << "平衡因子异常" << std::endl;   return false;}height = std::max(HeightLeft, HeightRight) + 1;return true;}bool IsBalance(){int height = 0;return _IsBalance(_root, height);}int _Height(Node* root){if (root == nullptr)return 0;return std::max(Height(root->_left), Height(root->_right)) + 1;}int Height(){return _Height(_root);}
private:Node* _root = nullptr;
};void TestAVLTree1()
{int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };//int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };AVLTree<int, int> t;for (auto e : a){t.Insert(std::make_pair(e, e));}t.InOrder();std::cout << t.IsBalance() << std::endl;
}

test.cpp

#include "AVLTree.h"
#include <iostream>
using namespace std;int main()
{TestAVLTree1();return 0;
}

运行结果
在这里插入图片描述

7. AVL树的性能

AVL树是一棵绝对平衡的二叉搜索树,其要求每个节点的左右子树高度差的绝对值都不超过1,这样可以保证查询时高效的时间复杂度,即 l o g 2 ( N ) log_2 (N) log2(N)。但是如果要对AVL树做一些结构修改的操作,性能非常低下,比如:插入时要维护其绝对平衡,旋转的次数比较多,更差的是在删除时,有可能一直要让旋转持续到根的位置。因此:如果需要一种查询高效且有序的数据结构,而且数据的个数为静态的(即不会改变),可以考虑AVL树,但一个结构经常修改,就不太适合。


未完待续

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/873626.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端基础之JavaScript学习——函数的使用

大家好我是来自CSDN的前端寄术区博主PleaSure乐事&#xff0c;今天我们继续有关JavaScript的学习&#xff0c;使用的编译器为vscode&#xff0c;浏览器为谷歌浏览器。 函数的声明与使用 声明 在JavaScript当中函数的声明和其他语言类似&#xff0c;使用如下格式即可声明&…

实战篇(十):使用Processing创建可爱花朵:实现随机位置、大小和颜色的花朵

使用Processing创建可爱花朵 0.效果预览1. 引言2. 设置Processing环境3. 创建花朵类4. 实现花瓣绘制5. 绘制可爱的笑脸6. 鼠标点击生成花朵7. 完整代码8. 总结与扩展0.效果预览 在本教程中,我们将使用Processing编程语言来创建一个可爱的花朵生成器。通过封装花朵为一个类,并…

大语言模型-检索测评指标

1. MRR &#xff08;Mean Reciprocal Rank&#xff09;平均倒数排名&#xff1a; 衡量检索结果排序质量的指标。 计算方式&#xff1a; 对于每个查询&#xff0c;计算被正确检索的文档的最高排名的倒数的平均值&#xff0c;再对所有查询的平均值取均值。 意义&#xff1a; 衡量…

【STM32】按键控制LED光敏传感器控制蜂鸣器(江科大)

一、按键控制LED LED.c #include "stm32f10x.h" // Device header/*** 函 数&#xff1a;LED初始化* 参 数&#xff1a;无* 返 回 值&#xff1a;无*/ void LED_Init(void) {/*开启时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENAB…

199.二叉树的右视图(DFS)

给定一个二叉树的根节点 root&#xff0c;想象自己站在它的右侧&#xff0c;按照从顶部到底部的顺序&#xff0c;返回从右侧所能看到的节点值。 示例 1: 输入: [1,2,3,null,5,null,4] 输出: [1,3,4] 示例 2: 输入: [1,null,3] 输出: [1,3] 示例 3: 输入: [] 输出: [] 解题…

贪心算法总结(1)

一、贪心算法简介 常用方法&#xff1a;交换论证法、数学归纳法、反证法、分类讨论 二、柠檬水找零&#xff08;交换论证法&#xff09; . - 力扣&#xff08;LeetCode&#xff09; class Solution { public:bool lemonadeChange(vector<int>& bills) {int five0,t…

【考研数学】线代满分经验分享+备考复盘

我一战二战复习都听了李永乐的线代课&#xff0c;二战的时候只听了一遍强化&#xff0c;个人感觉没有很乱&#xff0c;永乐大帝的课逻辑还是很清晰的。 以下是我听向量这一章后根据听课内容和讲义例题总结的部分思维导图&#xff0c;永乐大帝讲课的时候也会特意点到线代前后联…

TK秘籍:深度剖析机房IP与住宅IP的利与弊

大家好&#xff0c;今天我们来聊聊TikTok运营中的一个重要环节——IP地址的选择。 想象一下&#xff0c;你在TikTok上发布视频&#xff0c;就像是在一个热闹的市集上摆摊&#xff0c;而IP地址就是你的摊位位置。选对了位置&#xff0c;你的摊位就能吸引更多顾客&#xff0c;也…

最小二乘求待定位点的位置(三维环境)|MATLAB

前言 之前发过三点法求待测点位置的程序讲解&#xff0c;哪个是二维的&#xff0c;见&#xff1a;基于伪逆的三点法距离求位置&#xff0c;MATLAB源代码&#xff08;MATLAB函数&#xff09; 这里给出三维情况下的函数和测试代码。对于函数&#xff0c;输入已知锚点的位置、待…

JavaEE:Spring Web简单小项目实践三(留言板实现)

学习目的&#xff1a; 1、理解前后端交互过程 2、学习接口传参&#xff0c;数据返回以及页面展示 目录 1、准备工作 2、约定前后端交互接口 1、获取全部留言 2、发表新留言 3、实现服务器端代码 4、调整前端页面代码 5、运行测试 1、准备工作 创建SpringBoot项目&#x…

Linux 服务器管理和维护

Linux 是一个非常严谨的操作系统&#xff0c;每个目录都有自己的作用&#xff0c;这些作用是固定的&#xff0c;没有特殊情况&#xff0c;应严格执行&#xff1b; Linux 中所有东西以文件形式存储和管理&#xff0c;命令也不例外&#xff1b; 以下四个 bin 是二进制文件&…

SVM 技能测试:25 个 MCQ 用于测试数据科学家的 SVM

SVM 技能测试:25 个 MCQ 用于测试数据科学家的 SVM(2024 年更新) 一、介绍 你可以把机器学习算法想象成一个装满斧头、剑和刀片的军械库。你有各种各样的工具,但你应该学会在正确的时间使用它们。打个比方,将“线性回归或逻辑回归”视为一把能够有效地切片和切块数据但…

LeetCode 739, 82, 106

文章目录 739. 每日温度题目链接标签思路代码 82. 删除排序链表中的重复元素 II题目链接标签思路代码 106. 从中序与后序遍历序列构造二叉树题目链接标签思路二叉树的三种遍历值与索引的映射对于后序遍历的使用对于中序遍历的使用 代码 739. 每日温度 题目链接 739. 每日温度…

jenkins 插件版本冲突

一、Jenkins安装git parameter 插件重启后报错与临时解决方案 cd /root/.jenkins cp config.xml config.xml.bak vim config.xml <authorizationStrategy class"hudson.security.FullControlOnceLoggedInAuthorizationStrategy"><denyAnonymousReadAcces…

【工具使用】EMACS的verilog_mode脚本

#工作记录# 俗话说不会玩连连看的工程师不是一个好的SoC工程师。 在做集成工作的时候&#xff0c;集成连线估计是一件比较繁琐且容易出错的事情&#xff0c;连线类型定义出错、位宽问题、连线众多等等问题&#xff0c;此时使用由Veripool带来的verilog_mode简直是令人神清气爽…

基于牛顿-拉夫逊优化算法(Newton-Raphson-based optimizer, NBRO)的无人机三维路径规划

牛顿-拉夫逊优化算法(Newton-Raphson-based optimizer, NBRO)是一种新型的元启发式算法&#xff08;智能优化算法&#xff09;&#xff0c;该成果由Sowmya等人于2024年2月发表在中科院2区Top SCI期刊《Engineering Applications of Artificial Intelligence》上。 1、算法原理…

制造运营管理系统(MOM系统),企业实现先进制造的关键一步

随着全球制造业的快速发展&#xff0c;企业对于生产效率和成本控制的要求日益增高。在这个背景下&#xff0c;制造运营管理系统&#xff08;MOM系统&#xff09;成为了企业提升竞争力的关键工具。盘古信息作为业内领先的智能制造解决方案提供商&#xff0c;其MOM系统更是以其卓…

首批通过 | 百度通过中国信通院H5端人脸识别安全能力评估工作

2024年5月&#xff0c;中国信息通信研究院人工智能研究所依托中国人工智能产业发展联盟安全治理委员会&#xff08;AIIA&#xff09;、“可信人脸应用守护计划”及多家企业代表共同开展《H5端人脸识别线上身份认证安全能力要求及评估方法》的编制工作&#xff0c;并基于该方法开…

COD论文笔记 Deep Gradient Learning for Efficient Camouflaged 2022

动机 这篇论文的动机在于解决伪装目标检测(COD)中的一个关键问题&#xff1a;在复杂背景下&#xff0c;伪装目标与背景的边界模糊&#xff0c;使得检测变得极其困难。现有的方法&#xff0c;如基于边界或不确定性的模型&#xff0c;通常仅响应于伪装目标的稀疏边缘&#xff0c…

如何定位Milvus性能瓶颈并优化

假设您拥有一台强大的计算机系统或一个应用&#xff0c;用于快速执行各种任务。但是&#xff0c;系统中有一个组件的速度跟不上其他部分&#xff0c;这个性能不佳的组件拉低了系统的整体性能&#xff0c;成为了整个系统的瓶颈。在软件领域中&#xff0c;瓶颈是指整个路径中吞吐…