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

【重走C++学习之路】16、AVL树

目录

一、概念

二、AVL树的模拟实现

2.1 AVL树节点定义

2.2 AVL树的基本结构 

2.3 AVL树的插入

1. 插入步骤

2. 调节平衡因子

3. 旋转处理 

 4. 开始插入

2.4 AVL树的查找

2.5 AVL树的删除

1. 删除步骤

2. 调节平衡因子

3. 旋转处理

4. 开始删除

结语


一、概念

二叉搜索树查找效率为O(logN),但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率变为O(N),效率低下。

因此,两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年发明了一种解决上述问题的方法:当向二叉搜索树中插入新节点后,如果能保证每个节点的左右子树高度之差的绝对值不超过1(超过则需要对树中的节点进行调整),即可降低树的高度,从而减少平均搜索长度。

AVL树具有以下特点:

  • 它的左右子树都是AVL树
  • 左右子树高度之差(简称平衡因子)的绝对值不超过1(-1/01)

平衡因子的取值由自己规定,在这里为了模拟实现,规定左子树的高度在根结点中为负值,右子树的高度在根结点中为正值,即平衡因子= 右子树高度 - 左子树高度

二、AVL树的模拟实现

2.1 AVL树节点定义

template<class K, class V>
struct AVLTreeNode
{AVLTreeNode<K, V>* _left;    // 该节点的左孩子AVLTreeNode<K, V>* _right;   // 该节点的右孩子AVLTreeNode<K, V>* _parent;  // 该节点的父结点pair<K, V> _kv;int _bf;                     // 该节点的平衡因子AVLTreeNode(const pair<K, V>& kv):_left(nullptr),_right(nullptr),_parent(nullptr),_kv(kv),_bf(0){}
};

2.2 AVL树的基本结构 

template <class K, class V>
class AVLTree
{typedef AVTreeNode<K, V> Node;
public:bool Insert(const std::pair<K, V>& kv);bool Find(const K& key);bool Erase(const K& key);private:Node* _root = nullptr;
};

2.3 AVL树的插入

1. 插入步骤

  1. 按照二叉搜索树的方式插入新节点
  2. 调整节点的平衡因子

2. 调节平衡因子

插入节点后,会影响该节点到根节点这一条路径上节点的平衡因子,因此需要进行迭代,将这一条路径上的平衡因子更新。

步骤:

第一步: 对插入的节点的父节点进行更新,会发生两种情况:

  1. 如果插入的是根节点,则无父节点,不用更新。
  2. 如果插入的是父节点的左节点,则父节点的平衡因子-1;如果插入的是父节点的右节点,则父节点的平衡因子+1。

第二步: 父节点的平衡因子在插入节点后会有三种变化,也对应着三种措施:

  1. 父节点的平衡因子变为0,则说明在插入前两颗子树高度相差1,插入后整体的高度没有发生变化,不需要向上继续调整。
  2. 父节点的平衡因子变为-1或1,则说明在插入前两颗子树高度相等,插入后整体的高度+1,需要对父节点的父节点的平衡因子进行更新,这样就回到了步骤一。
  3. 父节点的平衡因子变为-2或2,则说明在插入前两个子树高度相差1,且插入的节点为高度较高的那颗子树的叶子节点,这导致了高度相差变为2,需要进行旋转处理,降低树的高度,从而达到平衡整颗树的要求。

图解:

第一种情况:

第二种情况:

可以看到这里在更新平衡因子的时候,只会影响节点到根节点路径上的节点的平衡因子,其它的节点不需要考虑。

第三种情况:

更新平衡因子的时候,发现不满足规则后,直接停止更新,转而进行旋转处理。

3. 旋转处理 

旋转有四种情况:

第一种情况:右单旋

新节点插入到较高左子树的左侧,左侧的高度变高需要将右边的调整下来,因此叫做右单旋。

具体操作:

让subL的右孩子成为parent的左孩子,然后让parent成为subL的右孩子,最后把两个节点的平衡因子修改为0。

 图解:

实现代码:

void RotateR(Node* parent)
{Node* subL = parent->_left;Node* subLR = subL->_right;// 1.先让把subL的右边作为parent的左边parent->_left = subLR;// 2.如果subLR不为空,就让subLR的父指针指向parentif (subLR) subLR->_parent = parent;// 3.记录parent的父节点的位置,然后把parent作为subL的右边Node* pParent = parent->_parent;subL->_right = parent;// 4.parent的父指针指向subLparent->_parent = subL;// 5.如果ppNode为空,说明subR现在是根节点,就让subL的父指针指向nullptr//   不是根节点就把subL的父指针指向parent的父节点,parent的父节点(左或右)指向subLif (pParent == nullptr){// 更新根节点_root = subL;subL->_parent = nullptr;}else{// 判断parent是pparent的左还是右if (pParent->_left == parent)pParent->_left = subL;elsepParent->_right = subL;subL->_parent = pParent;}// 6.把parent和subL的平衡因子更新为0subL->_bf = parent->_bf = 0;
}

第二种情况:左单旋 

新节点插入到较高右子树的右侧,右侧的高度变高需要将左边的调整下来,因此叫做右单旋。

 具体操作:

让subR的左孩子成为parent的右孩子,然后让parent成为subR的左孩子,最后把两个节点的平衡因子修改为0。

图解:

实现代码:

void RotateL(Node* parent)
{		Node* subR = parent->_right;Node* subRL = subR->_left;// 1.先让把subR的左边作为parent的右边parent->_right = subRL;// 2.如果subRL不为空,就让subRL的父指针指向parentif (subRL) subRL->_parent = parent;// 3.先记录parent的父节点的位置,然后把parent作为subR的左边 Node* pParent = parent->_parent;subR->_left = parent;// 4.parent的父指针指向subRparent->_parent = subR;// 5.如果ppNode为空,说明subR现在是根节点,就让subR的父指针指向nullptr//   不是根节点就把subR的父指针指向parent的父节点,parent的父节点(左或右)指向subRif (pParent == nullptr){// 更新根节点_root = subR;subR->_parent = nullptr;}else{// 判断parent是ppNode的左还是右if (pParent->_left == parent)pParent->_left = subR;elsepParent->_right = subR;subR->_parent = pParent;}// 6.把parent和subR的平衡因子更新为0subR->_bf = parent->_bf = 0;
}

第三种情况:左右双旋 

新节点插入在较高左子树右侧,这里和第一种情况的区别就是前者是直线,后者是折线

具体操作:

先对subL进行一个左单旋,然后对parent进行右单旋,修改平衡因子,有三种改法。三个节点从左至右的三个节点一次是:subL、subLR和parent。
如果subLR的平衡因子为0,就将它们依次改为0,0, 0;
如果subLR的平衡因子为1,就将它们依次改为-1,0, 0;
如果subLR的平衡因子为-1,就将它们依次改为0,0, 1。

图解:(这里只画出了一种情况,剩下的类似)

实现代码:

void RotateLR(Node* parent)
{Node* subL = parent->_left;Node* subLR = subL->_right;int bf = subLR->_bf;// 保留subLR的平衡因子的值,方便知道新插入的节点是在subLR的左子树还是右子树// 旋转 先对subL进行左旋转,再对parent进行右旋转RotateL(subL);RotateR(parent);// 从左到右 subL subLR parentif (bf == -1)// subLR的左子树  bf: 0 0 1{subL->_bf = 0;subLR->_bf = 0;parent->_bf = 1;}else if (bf == 1)// subLR的右子树 bf: -1 0 0{subL->_bf = -1;subLR->_bf = 0;parent->_bf = 0;}else if (bf == 0){subL->_bf = 0;subLR->_bf = 0;parent->_bf = 0;}
}

第四种情况:右左单旋 

新节点插入在较高右子树左侧,这里和第二种情况的区别就是前者是直线,后者是折线

 具体操作:

先对subR进行一个右单旋,然后对parent进行左单旋,修改平衡因子,有三种改法。三个节点从左至右的三个节点一次是:parent、subRL和subR。
如果subRL的平衡因子为0,就将它们依次改为0,0, 0;
如果subRL的平衡因子为1,就将它们依次改为-1,0, 0;
如果subRL的平衡因子为-1,就将它们依次改为0,0, 1。

图解:(这里只画出了一种情况,剩下的类似)

实现代码:

void RotateRL(Node* parent)
{Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;// 保留subRL的平衡因子的值,方便知道新插入的节点是在subRL的左子树还是右子树// 旋转 先对subR进行右旋转,再对parent进行左旋转RotateR(subR);RotateL(parent);// 从左到右 parent subRL subRif (bf == -1)// subRL的左子树  bf: 0 0 1{parent->_bf = 0;subRL->_bf = 0;subR->_bf = 1;}else if (bf == 1)// subRL的右子树 bf: -1 0 0{parent->_bf = -1;subRL->_bf = 0;subR->_bf = 0;}else if (bf == 0){parent->_bf = 0;subRL->_bf = 0;subR->_bf = 0;}
}

 4. 开始插入

bool Insert(const pair<K, V>& kv)
{// 先按照二叉搜索数一样插入元素// 无节点是插入if (_root == nullptr){_root = new Node(kv);return true;}// 有节点时插入Node* parent = nullptr;Node* cur = _root;while (cur){parent = cur;// 小于往左走if (kv.first < cur->_kv.first){cur = cur->_left;}// 大于往右走else if (kv.first > cur->_kv.first){cur = cur->_right;}else{// 找到了,就返回falsereturn false;}}cur = new Node(kv);// 判断cur应该插在parent的左还是右 // 小于在左,大于在右		if (cur->_kv.first < parent->_kv.first){parent->_left = cur;cur->_parent = parent;}else{parent->_right = cur;cur->_parent = parent;}// 更新parent的平衡因子// 节点的插入只会影响cur的祖先的平衡因子(不是所有的,是一部分,分情况)while (parent){// 更新parent的平衡因子// cur在parent的左,parent->_bf--// cur在parent的右,parent->_bf++if (cur == parent->_left)parent->_bf--;elseparent->_bf++;// bf 可能为 -2、-1、0、1、2if (parent->_bf == 0){// 对上层无影响,退出break;}else if (parent->_bf == -1 || parent->_bf == 1){// 对上层有影响,迭代更新cur = parent;parent = parent->_parent;}else{// 平衡树出现了问题,需要调整// 1.右边高,左旋转调整if (parent->_bf == 2){// 如果是一条直线==>左旋转即可// 如果是一条折线==>右左旋转if (cur->_bf == 1)RotateL(parent);else if (cur->_bf == -1)RotateRL(parent);}// 2.左边高,右旋转调整else if (parent->_bf == -2){// 如果是一条直线==>右旋转即可// 如果是一条折线==>左右旋转if (cur->_bf == -1)RotateR(parent);else if (cur->_bf == 1)RotateLR(parent);}// 调整后是平衡树,bf为0,不需要调整了break;}}return bool;
}

2.4 AVL树的查找

与二叉搜索树的过程一致,这里就不多解释了,直接上代码:

bool Find(const K& key)
{if (_root == nullptr)return false;Node* cur = _root;while (cur){// 小于往左走if (key < cur->_kv.first){cur = cur->_left;}// 大于往右走else if (key > cur->_kv.first){cur = cur->_right;}else{// 找到了return true;}}return false;
}

2.5 AVL树的删除

1. 删除步骤

  1. 我们先按照二叉搜索树树删除节点的方式,删除节点。
  2. 根据对应删除情况更新平衡因子,更新平衡因子的方法与插入的更新方法是相反的。

2. 调节平衡因子

步骤:

第一步:

  1. 删除节点后,如果删除的节点为根节点,就结束。
  2. 如果删除节点是父节点的左孩子,那么父节点的平衡因子加1;删除节点是父节点的右孩子,那么父节点的平衡因子减1。

第二步:父节点的平衡因子在插入节点后会有三种变化,也对应着三种措施:

  1. 父节点的平衡因子变为0,则说明删除前父亲的平衡因子为1或-1,多出一个左节点或右节点,删除节点后,左右高度相等,整体高度减1,对上层有影响,需要继续调节
  2. 父节点的平衡因子变为-1或1,则说明删除前父亲的平衡因子为0,左右高度相等,删除节点后,少了一个左节点或右节点,但是整体高度不变,对上层无影响,不需要继续调节
  3. 父节点的平衡因子变为-2或2,则说明删除前父亲的平衡因子为-1或1,多了一个左节点或一个右节点,删除了一个右节点或左节点,此时多了两个左节点和右节点,这棵子树一边已经被拉高了,此时这棵子树不平衡了,需要旋转处理

3. 旋转处理

这里的旋转与插入时旋转的没有区别,就不详细解答了,直接上代码。

4. 开始删除

bool Erase(const K& key)
{if (_root == nullptr)return false;// 有节点时插入Node* parent = nullptr;Node* cur = _root;while (cur){// 小于往左走if (key < cur->_kv.first){parent = cur;cur = cur->_left;}// 大于往右走else if (key > cur->_kv.first){parent = cur;cur = cur->_right;}else{// 找到了// 1.左边为空,把parent指向cur的右// 2.右边为空,把parent指向cur的左// 3.左右都不为空,用右子树的最左边的节点的值替换要删除的节点,然后转换为用1的情况删除该节点if (cur->_left == nullptr){if (cur == _root){_root = cur->_right;delete cur;break;}else{if (parent->_left == cur){parent->_left = cur->_right;parent->_bf++;}else{parent->_right = cur->_right;parent->_bf--;}}if (parent->_bf != -1 && parent->_bf != 1) UpdateBf(parent);delete cur;}else if (cur->_right == nullptr){if (cur == _root){_root = cur->_left;delete cur;break;}else{if (parent->_left == cur){parent->_left = cur->_left;parent->_bf++;}else{parent->_right = cur->_left;parent->_bf--;}}if (parent->_bf != -1 && parent->_bf != 1) UpdateBf(parent);delete cur;}else{Node* rightMinParent = cur;Node* rightMin = cur->_right;// 先去右子树while (rightMin->_left){rightMinParent = rightMin;rightMin = rightMin->_left;// 一种往左走}cur->_kv = rightMin->_kv;// 替代删除// 删除minNode  第一种情况:左节点为空if (rightMinParent->_left == rightMin){rightMinParent->_left = rightMin->_right;rightMinParent->_bf++;}else{rightMinParent->_right = rightMin->_right;rightMinParent->_bf--;}if (rightMinParent->_bf != -1 && rightMinParent->_bf != 1)                 UpdateBf(rightMinParent);delete rightMin;}return true;}}return false;
}void UpdateBf(Node* parent)
{if (parent == nullptr)return;Node* cur = parent;goto first;while (parent){// 更新parent的平衡因子// cur在parent的左,parent->_bf++// cur在parent的右,parent->_bf--if (cur == parent->_left)parent->_bf++;elseparent->_bf--;// bf 可能为 -2、-1、0、1、2first:if (parent->_bf == 0){// 对上层有影响,迭代更新// 如果parent是根节点就结束if (parent->_parent == nullptr)break;cur = parent;parent = parent->_parent;}else if (parent->_bf == -1 || parent->_bf == 1){// 对上层无影响,退出break;}else{// 平衡树出现了问题,需要调整// 1.右边高,左旋转调整if (parent->_bf == 2){// 如果是一条直线==>左旋转即可// 如果是一条折线==>右左旋转if (parent->_right->_bf == 1){RotateL(parent);cur = parent->_parent;parent = cur->_parent;continue;}else if (parent->_right->_bf == -1)// 调整后 p sL s  如果sL是1或-1可以退出 {Node* s = parent->_right;Node* sL = s->_left;RotateRL(parent);// 不平衡向上调整if (sL->_bf != 1 && sL->_bf != -1){cur = sL;parent = cur->_parent;continue;}}else if (parent->_right->_bf == 0)    // 平衡因子修改{RotateL(parent);parent->_bf = 1;parent->_parent->_bf = -1;}}// 2.左边高,右旋转调整else if (parent->_bf == -2){// 如果是一条直线==>右旋转即可// 如果是一条折线==>左右旋转if (parent->_left->_bf == -1){RotateR(parent);cur = parent->_parent;parent = cur->_parent;continue;    //parent不是-1或1就继续}else if (parent->_left->_bf == 1)// 调整后 s sR p  如果sL是1或-1可以退出{Node* s = parent->_left;Node* sR = s->_right;RotateLR(parent);// 不平衡向上调整 为0时如果parent为根//if (sR->_bf != 1 && sR->_bf != -1){cur = sR;parent = cur->_parent;continue;}}else if (parent->_left->_bf == 0)    // 平衡因子修改{RotateR(parent);parent->_parent->_bf = 1;parent->_bf = -1;}}// 调整后是平衡树,bf为1或-1,不需要调整了break;}}
}

结语

上面这些是AVL树的大致内容,其中旋转是有些难的地方,但是面试会考察,需要着重掌握,而删除是二叉搜索树的删除加上旋转的叠加,难度更上一层了,这里如果没能理解,可以自己画一画图,并且配合着插入的图来分析,应该会有所帮助。

下一篇将会介绍二叉搜索树的另一种改良:红黑树,有兴趣的朋友可以关注一下。

相关文章:

【重走C++学习之路】16、AVL树

目录 一、概念 二、AVL树的模拟实现 2.1 AVL树节点定义 2.2 AVL树的基本结构 2.3 AVL树的插入 1. 插入步骤 2. 调节平衡因子 3. 旋转处理 4. 开始插入 2.4 AVL树的查找 2.5 AVL树的删除 1. 删除步骤 2. 调节平衡因子 3. 旋转处理 4. 开始删除 结语 一、概念 …...

蓝桥杯 19.合根植物

合根植物 原题目链接 题目描述 W 星球的一个种植园被分成 m n 个小格子&#xff08;东西方向 m 行&#xff0c;南北方向 n 列&#xff09;。每个格子里种了一株合根植物。 这种植物有个特点&#xff0c;它的根可能会沿着南北或东西方向伸展&#xff0c;从而与另一个格子的…...

爆改 toxml 组件 支持数据双向绑定 解决数据刷新问题

GGGGGGGGGGGGGGGGGithub地址自行研究 sbfkcel/towxml: 微信小程序HTML、Markdown渲染库https://github.com/sbfkcel/towxml原组件是以导入数据渲染信息为目的、本文以AI数据返回小程序为模拟效果演示 默认情况只在ready 环节进行渲染静态资源 1、对传入数据容器的位置做处理 …...

6.分布式数据库与分库分表

目录 一、分库分表核心概念 • 核心目标&#xff1a;突破单库性能瓶颈&#xff0c;应对海量数据与高并发 • ​​垂直拆分​​&#xff1a;按业务模块拆分&#xff08;用户库、订单库、商品库&#xff09; • ​​水平拆分​​&#xff1a;单表数据分片&#xff08;用户ID取模…...

基于javaweb的SSM+Maven小区失物招领系统设计与实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…...

Kubernetes finalize | namespace卡Terminatingfinalizers删除失败

目录 1、为什么会卡住&#xff1f;2、强制删除卡住的 Namespace&#xff1a;操作步骤1&#xff1a;导出当前 namespace 信息2&#xff1a;启动代理&#xff08;另一个终端&#xff09;以便使用 Kubernetes API Server3&#xff1a;使用 curl 强制删除 finalize 3、进阶排查&…...

Java数组

目录 一、定义 二、使用 2.1遍历数组 2.2获取数组长度 三、Arrays类 3.1数组填充 3.2数组排序 3.3数组转为字符串 3.4数组比较 3.5二分搜索 3.6数组复制 二维数组 一、定义 数组表示一个相同类型元素的集合 对于一个数组&#xff0c;可以有以下几种定义方法 int[…...

高级java每日一道面试题-2025年4月22日-基础篇[反射篇]-如何通过反射创建一个对象实例?

如果有遗漏,评论区告诉我进行补充 面试官: 如何通过反射创建一个对象实例&#xff1f; 我回答: 在Java中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的工具&#xff0c;允许程序在运行时检查和操作类、接口、字段和方法。反射不仅用于检查类的结构&#…...

Spring开发系列教程(26)——异步处理

在Servlet模型中&#xff0c;每个请求都是由某个线程处理&#xff0c;然后&#xff0c;将响应写入IO流&#xff0c;发送给客户端。从开始处理请求&#xff0c;到写入响应完成&#xff0c;都是在同一个线程中处理的。 实现Servlet容器的时候&#xff0c;只要每处理一个请求&…...

【2025最新Java面试八股】如何理解MySQL的MVCC机制?

面试回答要点 当面试官问及MySQL的MVCC机制时&#xff0c;可以这样组织回答&#xff1a; "MVCC(Multi-Version Concurrency Control&#xff0c;多版本并发控制)是MySQL实现高并发事务的一种重要机制&#xff0c;它通过保存数据在某个时间点的快照来实现非阻塞读操作。I…...

使用FreeRTOS解决单片机串口异步打印

单片机串口异步打印 文章目录 单片机串口异步打印前言设计思路准备队列创建完整代码 总结 前言 &#x1f30a;在单片机开发中串口的异步打印异步打印允许单片机在执行其他任务的同时进行打印操作&#xff0c;无需等待打印完成后再继续执行后续代码&#xff0c;避免了在多处调用…...

飞算 JavaAI 与 Spring Boot:如何实现微服务开发效率翻倍?

微服务架构凭借其高内聚、低耦合的特性&#xff0c;成为企业构建复杂应用系统的首选方案。然而&#xff0c;传统微服务开发流程中&#xff0c;从服务拆分、接口设计到代码编写、调试部署&#xff0c;往往需要耗费大量时间与人力成本。Spring Boot 作为 Java 领域最受欢迎的微服…...

Python 列表与元组深度解析:从基础概念到函数实现全攻略

在 Python 编程的广袤天地中&#xff0c;列表&#xff08;List&#xff09;和元组&#xff08;Tuple&#xff09;是两种不可或缺的数据结构。它们如同程序员手中的瑞士军刀&#xff0c;能高效地处理各类数据。从简单的数值存储到复杂的数据组织&#xff0c;列表和元组都发挥着关…...

vue 修改路由动态选择路由 改文件位置

vue 修改路由动态选择路由 改文件位置 main.jspermission.js...

Nginx openresty web服务 与 Go 原生web服务性能对比

1 概述 Nginx采用的是IO复用模型&#xff0c;能处理超高并发。 Go语言采用协程&#xff0c;能轻量级的处理超高并发。 那么在不考虑业务逻辑复杂的前提下&#xff0c;即假如将Nginx和Go都提供一个/test接口&#xff0c;并在接口逻辑中都只是让其做20毫秒的耗时操作&#xff0c…...

【音视频】FFmpeg解封装

解封装 复用器&#xff0c;比如MP4/FLV 解复用器&#xff0c;MP4/FLV 封装格式相关函数 avformat_alloc_context(); 负责申请一个AVFormatContext结构的内存,并进行简单初始化avformat_free_context(); 释放该结构里的所有东西以及该结构本身avformat_close_input();关闭解复…...

autohue.js - 基于 JavaScript 开发的图片背景色提取开源库,能让图片和背景融为一体

图片提取主题色的工具库&#xff0c;可以实现一些酷炫的界面效果。 本文不是 AI 生成&#xff0c;大部分文字都是我自己敲键盘&#xff0c;部分文字摘自 autohue.js 作者主页&#xff0c;请各位放心舒适阅读。 autohue.js 是一个图片背景色提取库&#xff0c;基于提出来的颜色…...

bgp实验.包括联盟,隧道相关,以及一个低级错误

实验拓扑 低级错误 在配置隧道时,目标的单词是destination,我自动补全为description了,这个问题花了我40分钟 划分ip AS2内骨干网,一个网段需要两个地址,主机位2位,掩码30 需要6个 172.16.0.000000 00 172.16.0.0/30 172.16.0.000001 00 172.16.0.4/30 172.16.0.000010 00 1…...

科普动画短视频制作:角色塑造的魅力法则

宝子们&#xff0c;在科普动画短视频的世界里&#xff0c;角色塑造可是让作品出彩的关键&#xff01;今天就来和大家唠唠那些超实用的角色塑造法则&#xff0c;还会给大家推荐一款超好用的工具哦~ 一、独特外形&#xff0c;吸睛第一步 在科普动画短视频制作中&#xff0c;角色…...

【飞渡科技数字孪生虚拟环境部署与集成教程 - CloudMaster实战指南】

飞渡科技数字孪生虚拟环境部署与集成教程 - CloudMaster实战指南 前言 本教程详细记录了飞渡科技的数字孪生平台CloudMaster的配置过程&#xff0c;以及如何将三维数字孪生场景集成到前端项目中。数字孪生技术能够在虚拟环境中精确复现物理实体的数据、特性和行为&#xff0c…...

MongoDB 集合名称映射问题

项目场景 在使用 Spring Data MongoDB 进行开发时&#xff0c;定义了一个名为 CompetitionSignUpLog 的实体类&#xff0c;并创建了对应的 Repository 接口。需要明确该实体类在 MongoDB 中实际对应的集合名称是 CompetitionSignUpLog 还是 competitionSignUpLog。 问题描述 …...

禁止ubuntu自动更新

由于ubuntu server和desktop版本都默认 启动了&#xff0c;自动更新内核的操作。这对于生 产环境来说是不友好的。容易导致亿赛通 无法启动 默认开启了内核自动更新所以我们关闭自 动内核更新。 1.禁止更新执行 sudo apt-mark hold linux-image-generic linux-headers-generic…...

【C++】——入门基础(一)

前言 这是我C的第一篇文章&#xff0c;如果你想从事入门C行业&#xff0c;可以看看这幅漫画 当然&#xff0c;这只是一个玩笑&#xff0c;但如过你真的想学习C&#xff0c;和我一起学习吧 本人其他博客;恋风诗 本文出现的代码见gitte:mozhengy 这里写目录标题 前言1. C发展历史…...

[原创](现代Delphi 12指南):[macOS 64bit App开发]:在Mac App Store外创建、部署与公证

[作者] 常用网名: 猪头三 出生日期: 1981.XX.XX 企鹅交流: 643439947 个人网站: 80x86汇编小站 编程生涯: 2001年~至今[共24年] 职业生涯: 22年 开发语言: C/C++、80x86ASM、Object Pascal、Objective-C、C#、R、Python、PHP、Perl、 开发工具: Visual Studio、Delphi、XCode、…...

美乐迪电玩客户端打包与资源替换实战教程

本篇为《美乐迪电玩全套系统搭建》系列的第二篇&#xff0c;聚焦客户端层的实战操作&#xff0c;主要面向前端开发者、美术资源替换人员及整体项目的打包部署人员。教程将涵盖安卓客户端的构建、资源目录说明、动画素材替换方式及常见适配问题处理等。 一、客户端项目结构说明&…...

多态以及多态底层的实现原理

本章目标 1.多态的概念 2.多态的定义实现 3.虚函数 4.多态的原理 1.多态的概念 多态作为面对三大特性之一,它所指代的和它的名字一样,多种形态.但是这个多种形态更多的指代是函数的多种形态. 多态分为静态多态和动态多态. 静态多态在前面已经学习过了,就是函数重载以及模板,…...

描述城市出行需求模式的复杂网络视角:大规模起点-目的地需求网络的图论分析

描述城市出行需求模式的复杂网络视角&#xff1a;大规模起点-目的地需求网络的图论分析 原文&#xff1a; A complex network perspective for characterizing urban travel demand patterns: graph theoretical analysis of large-scale origin–destination demand networks…...

文件操作函数

本文是小编巩固自身而作&#xff0c;如有错误&#xff0c;欢迎指出&#xff01; 1.使用文件的原因 我们编写的程序都是有生命周期的&#xff0c;储存在电脑的内存中&#xff0c;如果程序退出&#xff0c;内存回收&#xff0c;数据就会丢失&#xff0c;等程序再次运行&#xf…...

Java高频面试之并发编程-05

hello啊&#xff0c;各位观众姥爷们&#xff01;&#xff01;&#xff01;本baby今天来报道了&#xff01;哈哈哈哈哈嗝&#x1f436; 面试官&#xff1a;线程有哪些调度方法&#xff1f; 在Java中&#xff0c;线程的调用方法主要包括以下几种方式&#xff0c;每种方式适用于…...

LeetCode 1292 元素和小于等于阈值的正方形的最大边长

最大正方形边长问题详解 一、问题描述 给定一个大小为 mn 的矩阵 mat 和一个整数阈值 threshold&#xff0c;要求返回元素总和小于或等于阈值的正方形区域的最大边长&#xff1b;如果没有这样的正方形区域&#xff0c;则返回 0。 二、解题思路 前缀和矩阵的概念与构建 前缀…...

测试开发 - Java 自动化测试核心函数详解

目录 1. 元素定位 1.1 By.xpath 1.1.1 //* 1.1.2 //[指定节点] 1.1.3 / 1.1.4 /.. 1.1.5 [...] 1.1.6 指定索引获取对应元素 1.2 By.cssSelector 1.2.1 # 1.2.2 . 1.2.3 > 1.2.4 标签名:nth-child(n) 2. 获取元素 2.1 findElement 2.2 findElements 3. 操…...

【HarmonyOS】ArKUI框架

目录 概述 声明式开发范式 基于ArKUI的项目 • 1&#xff0e;创建资源文件 • 2&#xff0e;引用资源 • 3&#xff0e;引用系统资源&#xff1a; • 系统资源有哪些 • 4. 在配置和资源中引用资源 声明式语法 UI描述规范 UI组件概述 组件化 组件渲染控制语法 修改…...

【MQ篇】RabbitMQ之简单模式!

目录 引言一、 初识 RabbitMQ 与工作模式二、 简单模式 (Simple Queue) 详解&#xff1a;最直接的“点对点快递” &#x1f4ee;三、 Java (Spring Boot) 代码实战&#xff1a;让小兔子跑起来&#xff01; &#x1f430;&#x1f3c3;‍♂️四、 深入理解&#xff1a;简单模式的…...

K8S节点出现Evicted状态“被驱逐”

在Kubernetes集群中&#xff0c;Pod状态为“被驱逐&#xff08;evicted&#xff09;”表示Pod无法在当前节点上继续运行&#xff0c;已被集群从节点上移除。 问题分析&#xff1a; 节点磁盘空间不足 &#xff0c;使用df -h查看磁盘使用情况 可以看到根目录 / 已100%满&#x…...

NumPyro:概率编程的现代Python框架深度解析

引言 概率编程作为统计学与机器学习的交叉领域&#xff0c;正在重塑我们构建不确定性模型的方式。在众多概率编程语言&#xff08;PPL&#xff09;中&#xff0c;NumPyro凭借其简洁的语法、强大的性能和与PyTorch生态系统的无缝集成&#xff0c;已经成为研究者和数据科学家的首…...

java进阶之git

git git介绍git常用命令代码回滚操作 git 介绍 工作区 改动&#xff08;增删文件和内容&#xff09;暂存区 输入命令&#xff1a;git add改动的文件名&#xff0c;此次改动就放到了"暂存区“本地仓库 输入命令&#xff1a;git commit 此次修改的描述&#xff0c;此次改动…...

负载阻尼效应及其作用解析

负载阻尼效应是指负载&#xff08;如电路、机械系统或控制系统中连接的设备&#xff09;对系统动态变化&#xff08;如电压波动、机械振动等&#xff09;产生的抑制或衰减作用。 其核心是通过消耗或吸收能量&#xff0c;减少系统中的振荡、波动或瞬态响应&#xff0c;从而提高…...

面向组织的网络安全措施

一、安全措施概述 在一个组织中&#xff0c;技术人员可以利用一系列强大的网络安全工具进行安全检测和防范&#xff0c;以保护组织的网络基础设施、数据和资产免受各种威胁。这些工具通常涵盖了从主动防御、威胁检测、漏洞管理到事件响应和安全分析的各个方面。 以下是一些关…...

Unity 跳转资源商店,并打开特定应用

需求&#xff1a; 打开资源商店&#xff0c;并定位到特定应用. 代码&#xff1a; #if UNITY_ANDROIDApplication.OpenURL("market://details?idcom.tencent.mm"); #elif UNITY_IPHONEApplication.OpenURL(“itms-apps://apps.apple.com/app/id333903271”); #end…...

2025年五大ETL数据集成工具推荐

ETL工具作为打通数据孤岛的核心引擎&#xff0c;直接影响着企业的决策效率与业务敏捷性。本文精选五款实战型ETL解决方案&#xff0c;从零门槛的国产免费工具到国际大厂企业级平台&#xff0c;助您找到最适合的数据集成利器。 一、谷云科技ETLCloud&#xff1a;国产数据集成工…...

基于 PaddleOCR对pdf文件中的文字提取

一、基于 PaddleOCR 提取 PDF 文件中的文字流程 1. 安装必要的依赖库&#xff1a;包括 PaddleOCR 和 PyMuPDF pip install paddlepaddle paddleocr pymupdf 2. 将 PDF 转换为图像&#xff1a;使用 PyMuPDF 将 PDF 的每一页转换为图像 3. 使用 PaddleOCR 进行文字识别&a…...

鸿蒙移动应用开发--渲染控制实验

任务&#xff1a;使用“对象数组”、“ForEach渲染”、“Badge角标组件”、“Grid布局”等相关知识&#xff0c;实现生效抽奖卡案例。如图1所示&#xff1a; 图1 生肖抽奖卡实例图 图1(a)中有6张生肖卡可以抽奖&#xff0c;每抽中一张&#xff0c;会通过弹层显示出来&#xf…...

【漫话机器学习系列】215.处理高度不平衡数据策略(Strategies For Highly Imbalanced Classes)

处理高度不平衡数据的四大策略详解 在机器学习与数据挖掘任务中&#xff0c;“类别不平衡”问题几乎无处不在。无论是信用卡欺诈检测、医疗异常诊断&#xff0c;还是网络攻击识别&#xff0c;正负样本的比例往往严重失衡。比如一个欺诈检测数据集中&#xff0c;可能只有不到 1…...

在离线 Ubuntu 环境下部署双 Neo4j 实例(Prod Dev)

在许多开发和生产场景中&#xff0c;我们可能需要在同一台服务器上运行多个独立的 Neo4j 数据库实例&#xff0c;例如一个用于生产环境 (Prod)&#xff0c;一个用于开发测试环境 (Dev)。本文将详细介绍如何在 离线 的 Ubuntu 服务器上&#xff0c;使用 tar.gz 包部署两个 Neo4j…...

Windows下Golang与Nuxt项目宝塔部署指南

在Windows下将Golang后端和Nuxt前端项目打包&#xff0c;并使用宝塔面板部署的步骤如下 一、Golang后端打包 交叉编译为Linux可执行文件 在Windows PowerShell中执行&#xff1a; powershell复制下载 $env:GOOS "linux" $env:GOARCH "amd64" go build…...

基于贝叶斯优化的Transformer多输入单输出回归预测模型Bayes-Transformer【MATLAB】

Bayes-Transformer 在机器学习和深度学习领域&#xff0c;Transformer模型已经广泛应用于自然语言处理、图像识别、时间序列预测等多个领域。然而&#xff0c;在一些实际应用中&#xff0c;我们面临着如何高效地优化模型超参数的问题。贝叶斯优化&#xff08;Bayesian Optimiz…...

ibus输入法微软词库分享

链接: https://pan.baidu.com/s/1aC-UvV-UDHEpxg5sZcAS2Q?pwddxpq 提取码: dxpq --来自百度网盘超级会员v8的分享 链接: https://pan.baidu.com/s/1aC-UvV-UDHEpxg5sZcAS2Q?pwddxpq 提取码: dxpq --来自百度网盘超级会员v8的分享 # 更改ibus输入法字体大小 sudo apt insta…...

Sharding-JDBC 系列专题 - 第五篇:分布式事务

Sharding-JDBC 系列专题 - 第五篇:分布式事务 本系列专题旨在帮助开发者全面掌握 Sharding-JDBC,一个轻量级的分布式数据库中间件。本篇作为系列的第五篇文章,将深入探讨 分布式事务(Distributed Transactions),包括其概念、支持的事务类型、配置方法、工作原理以及实战…...

力扣每日打卡17 49. 字母异位词分组 (中等)

力扣 49. 字母异位词分组 中等 前言一、题目内容二、解题方法1. 哈希函数2.官方题解2.1 前言2.2 方法一&#xff1a;排序2.2 方法二&#xff1a;计数 前言 这是刷算法题的第十七天&#xff0c;用到的语言是JS 题目&#xff1a;力扣 49. 字母异位词分组 (中等) 一、题目内容 给…...

深入解析C++ STL List:双向链表的特性与高级操作

一、引言 在C STL容器家族中&#xff0c;list作为双向链表容器&#xff0c;具有独特的性能特征。本文将通过完整代码示例&#xff0c;深入剖析链表的核心操作&#xff0c;揭示其底层实现机制&#xff0c;并对比其他容器的适用场景。文章包含4000余字详细解析&#xff0c;适合需…...