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

数据结构之BST、AVL、红黑树、哈夫曼树与B族树

数据结构之BST、AVL、红黑树、哈夫曼树与B族树

  • 数据结构之BST、AVL、红黑树、哈夫曼树与B族树
    • 一、二叉搜索树(Binary Search Tree, BST)
      • 1. 什么是二叉搜索树?
        • 重要性质
      • 2. 二叉搜索树实现
        • 1. 节点结构定义
        • 2. 核心操作接口
        • 3. 插入算法实现
        • 4. 删除算法实现(重点)
        • 5. 时间复杂度对比
      • 3. 实战测试示例
        • 测试代码
        • 测试树结构变化
    • 二、平衡二叉搜索树(AVL)
      • 1、AVL树的诞生背景
      • 2、核心平衡机制
        • 1. 平衡因子(Balance Factor)
        • 2. 失衡检测流程
      • 3、旋转操作详解
        • **1. LL型失衡(单右旋)**
        • **2. RR型失衡(单左旋)**
        • **3. LR型失衡(先左旋后右旋)**
        • **4. RL型失衡(先右旋后左旋)**
      • 4、完整插入流程
      • 5、时间复杂度分析
      • 6、实战案例:实现AVL树
        • 1. AVL树节点结构
        • 2. 单右旋(LL型失衡)
        • 3. 单左旋(RR型失衡)
        • 4. 获取节点高度、平衡因子
        • 5. 插入操作
        • 6. 完整实例代码
          • 代码说明
            • 1. LL型失衡(左左失衡)- 右旋操作
            • 2. RR型失衡(右右失衡)- 左旋操作
            • 3. LR型失衡(左右失衡)- 先左旋子树再右旋
            • 4. RL型失衡(右左失衡)- 先右旋子树再左旋
          • 测试用例输出
      • 7、典型应用场景
    • 三、哈夫曼树(Huffman Tree)
      • 1. 哈夫曼树定义
      • 2. 哈夫曼树构建过程
      • 3. 树结构流程图
      • 5. 代码实现
      • 6. 关键特性总结
    • 四、红黑树(Red-Black Tree)
      • 1. 什么是红黑树
      • 2. 红黑树插入
      • 3. 红黑树删除
      • 4. 红黑树实现
        • 测试用例输出
        • 红黑树结构流程图
      • 5. 红黑树特性总结
    • 五、B,B+,B*树
      • 1. B树
      • 2. B+树
      • 3. B*树
      • 4. B树实现
      • 4. B树的C++实现

数据结构之BST、AVL、红黑树、哈夫曼树与B族树


一、二叉搜索树(Binary Search Tree, BST)


1. 什么是二叉搜索树?

二叉搜索树(Binary Search Tree,BST)是一种特殊的二叉树数据结构,其中每个节点的值都大于其左子树中的任何节点的值,且小于其右子树中的任何节点的值。它的特点使得在搜索、插入和删除操作上具有高效性。

二叉搜索树是一种具有以下特性的二叉树:

  • 有序性
    • 左子树所有节点值 < 根节点值
    • 右子树所有节点值 > 根节点值
  • 递归性:左右子树也必须是二叉搜索树
  • 中序遍历结果是有序序列
8
3
10
1
6
9
14
4
7
重要性质
特性说明
查找效率平均O(log n),最坏O(n)
插入顺序影响形态有序插入会退化成链表
动态维护有序性无需显式排序,自动维护
支持范围查询通过中序遍历实现

2. 二叉搜索树实现

1. 节点结构定义
struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
2. 核心操作接口
class BST {
private:TreeNode* root;// 递归查找实现TreeNode* searchRec(TreeNode* node, int key) {if (!node || node->val == key) return node;return (key < node->val) ? searchRec(node->left, key) : searchRec(node->right, key);}public:BST() : root(nullptr) {}// 查找操作bool contains(int key) {return searchRec(root, key) != nullptr;}// 插入操作void insert(int key) {root = insertRec(root, key);}// 删除操作void remove(int key) {root = deleteRec(root, key);}
};
3. 插入算法实现
TreeNode* insertRec(TreeNode* node, int key) {if (!node) return new TreeNode(key);if (key < node->val) {node->left = insertRec(node->left, key);} else if (key > node->val) {node->right = insertRec(node->right, key);}return node;
}
4. 删除算法实现(重点)
TreeNode* deleteRec(TreeNode* root, int key) {if (!root) return nullptr;if (key < root->val) {root->left = deleteRec(root->left, key);} else if (key > root->val) {root->right = deleteRec(root->right, key);} else {// Case 1: 无左子树if (!root->left) {TreeNode* temp = root->right;delete root;return temp;}// Case 2: 无右子树else if (!root->right) {TreeNode* temp = root->left;delete root;return temp;}// Case 3: 左右子树均存在TreeNode* minNode = findMin(root->right);root->val = minNode->val;root->right = deleteRec(root->right, minNode->val);}return root;
}// 辅助函数:查找子树最小值节点
TreeNode* findMin(TreeNode* node) {while (node && node->left) {node = node->left;}return node;
}
5. 时间复杂度对比
操作平均时间复杂度最坏时间复杂度
插入O(log n)O(n)
删除O(log n)O(n)
查找O(log n)O(n)

3. 实战测试示例

测试代码
int main() {BST tree;// 插入测试vector<int> nums = {8, 3, 10, 1, 6, 14, 4, 7, 13};for (int num : nums) tree.insert(num);// 查找测试cout << "Contains 7: " << boolalpha << tree.contains(7) << endl;  // truecout << "Contains 5: " << boolalpha << tree.contains(5) << endl;  // false// 删除测试tree.remove(6);cout << "After delete 6, contains 6: " << tree.contains(6) << endl; // falsecout << "Now contains 4: " << tree.contains(4) << endl; // truereturn 0;
}
测试树结构变化
删除前:8/   \3     10/ \     \1   6     14/ \   /4  7 13删除6后:8/   \3     10/ \     \1   7     14/     /4     13

二、平衡二叉搜索树(AVL)

1、AVL树的诞生背景

核心问题:二叉搜索树在极端情况下会退化为链表结构,导致操作时间复杂度退化为O(n)

解决方案
1962年由Adelson-Velsky和Landis提出,通过动态平衡机制确保树的高度始终保持在O(log n)级别


2、核心平衡机制

1. 平衡因子(Balance Factor)
  • 定义BF(node) = height(left) - height(right)
  • 平衡条件:所有节点的平衡因子绝对值必须 ≤ 1
2. 失衡检测流程
BF > 1
BF < -1
插入/删除节点
向上回溯路径
检查BF值
左子树过高
右子树过高
执行旋转调整

3、旋转操作详解

1. LL型失衡(单右旋)

结构特征

  • 新节点插入在左子树的左子树
  • 失衡节点的平衡因子为 +2,其左子节点的平衡因子为 +1

文字示意图

    A (BF=+2)       → 右旋 →      B/                             / \B (BF=+1)                     C   A/
C (新插入节点)

操作步骤

  1. 将失衡节点 A 的左子节点 B 提升为新根
  2. 原根节点 A 成为 B 的右子节点
  3. B 的原有右子树(如果有)变为 A 的左子树

2. RR型失衡(单左旋)

结构特征

  • 新节点插入在右子树的右子树
  • 失衡节点的平衡因子为 -2,其右子节点的平衡因子为 -1

文字示意图

A (BF=-2)           → 左旋 →      B\                               / \B (BF=-1)                     A   C\C (新插入节点)

操作要点

  • 镜像操作与 LL 型相反
  • 注意右子树可能存在的左子树需要重新挂载

3. LR型失衡(先左旋后右旋)

结构特征

  • 新节点插入在左子树的右子树
  • 失衡节点的平衡因子为 +2,其左子节点的平衡因子为 -1

文字示意图

     A (BF=+2)       → 对 B 左旋 →   A (BF=+2)    → 对 A 右旋 →    C/                               /                            / \B (BF=-1)                       C                            B   A\                             /C (新插入节点)              B

关键步骤

  1. 先对失衡节点的左子节点 B 执行左旋(转换为 LL 型)
  2. 再对根节点 A 执行右旋

4. RL型失衡(先右旋后左旋)

结构特征

  • 新节点插入在右子树的左子树
  • 失衡节点的平衡因子为 -2,其右子节点的平衡因子为 +1

文字示意图

A (BF=-2)           → 对 B 右旋 →   A (BF=-2)    → 对 A 左旋 →     C\                                   \                           / \B (BF=+1)                           C                         A   B/                                     \
C (新插入节点)                           B

操作要点

  1. 先对失衡节点的右子节点 B 执行右旋(转换为 RR 型)
  2. 再对根节点 A 执行左旋

4、完整插入流程

BF>1
BF<-1
LL型
LR型
RR型
RL型
插入新节点
标准BST插入
更新路径节点高度
回溯检查平衡因子
检查左子树结构
检查右子树结构
执行右旋
执行左右双旋
执行左旋
执行右左双旋

5、时间复杂度分析

操作时间复杂度说明
查找O(log n)严格平衡保证树高
插入O(log n)最多两次旋转操作
删除O(log n)可能传播旋转到根节点
空间复杂度O(n)每个节点需存储高度/平衡因子

6、实战案例:实现AVL树

1. AVL树节点结构
struct AVLNode {int val;AVLNode* left;AVLNode* right;int height;  // 新增高度字段AVLNode(int x) : val(x), left(nullptr), right(nullptr), height(1) {}
};
2. 单右旋(LL型失衡)
AVLNode* rightRotate(AVLNode* y) {AVLNode* x = y->left;AVLNode* T2 = x->right;// 执行旋转x->right = y;y->left = T2;// 更新高度y->height = max(height(y->left), height(y->right)) + 1;x->height = max(height(x->left), height(x->right)) + 1;return x; // 返回新的根节点
}
3. 单左旋(RR型失衡)
AVLNode* leftRotate(AVLNode* x) {AVLNode* y = x->right;AVLNode* T2 = y->left;// 执行旋转y->left = x;x->right = T2;// 更新高度x->height = max(height(x->left), height(x->right)) + 1;y->height = max(height(y->left), height(y->right)) + 1;return y; // 返回新的根节点
}
4. 获取节点高度、平衡因子
// 获取节点高度
int height(AVLNode* node) {return node ? node->height : 0;
}// 获取平衡因子
int getBalance(AVLNode* node) {return node ? height(node->left) - height(node->right) : 0;
}
5. 插入操作
AVLNode* insert(AVLNode* node, int key) 
{// 标准BST插入if (!node) return new AVLNode(key);if (key < node->val)node->left = insert(node->left, key);else if (key > node->val)node->right = insert(node->right, key);else return node; // 不允许重复值// 更新高度node->height = 1 + max(height(node->left), height(node->right));// 获取平衡因子int balance = getBalance(node);// LL型失衡if (balance > 1 && key < node->left->val)return rightRotate(node);// RR型失衡if (balance < -1 && key > node->right->val)return leftRotate(node);// LR型失衡if (balance > 1 && key > node->left->val) {node->left = leftRotate(node->left);return rightRotate(node);}// RL型失衡if (balance < -1 && key < node->right->val) {node->right = rightRotate(node->right);return leftRotate(node);}return node;
}
6. 完整实例代码

以下是完整的 AVL树C++实现,包含插入、删除、遍历等功能,并附带测试用例:

#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;struct AVLNode {int val;AVLNode* left;AVLNode* right;int height;AVLNode(int x) : val(x), left(nullptr), right(nullptr), height(1) {}
};class AVLTree {
private:AVLNode* root;// 获取节点高度int height(AVLNode* node) {return node ? node->height : 0;}// 计算平衡因子int getBalance(AVLNode* node) {return node ? height(node->left) - height(node->right) : 0;}// 单右旋(LL型)AVLNode* rightRotate(AVLNode* y) {AVLNode* x = y->left;AVLNode* T2 = x->right;x->right = y;y->left = T2;y->height = max(height(y->left), height(y->right)) + 1;x->height = max(height(x->left), height(x->right)) + 1;return x;}// 单左旋(RR型)AVLNode* leftRotate(AVLNode* x) {AVLNode* y = x->right;AVLNode* T2 = y->left;y->left = x;x->right = T2;x->height = max(height(x->left), height(x->right)) + 1;y->height = max(height(y->left), height(y->right)) + 1;return y;}// 查找最小节点AVLNode* minValueNode(AVLNode* node) {AVLNode* current = node;while (current->left)current = current->left;return current;}public:AVLTree() : root(nullptr) {}// 插入操作(外部接口)void insert(int val) {root = insert(root, val);}// 删除操作(外部接口)void remove(int val) {root = remove(root, val);}// 搜索功能bool search(int val) {return search(root, val);}// 中序遍历void inOrder() {inOrder(root);cout << endl;}// 前序遍历void preOrder() {preOrder(root);cout << endl;}// 层序遍历显示函数(用于验证树结构)void printLevelOrder() {if (!root) {cout << "空树" << endl;return;}queue<AVLNode*> q;q.push(root);while (!q.empty()) {int size = q.size();while (size--) {AVLNode* node = q.front();q.pop();cout << node->val << " "; if (node->left) q.push(node->left);if (node->right) q.push(node->right);}cout << endl;}}private:// 递归插入实现AVLNode* insert(AVLNode* node, int val) {if (!node) return new AVLNode(val);if (val < node->val)node->left = insert(node->left, val);else if (val > node->val)node->right = insert(node->right, val);elsereturn node; // 不允许重复值node->height = 1 + max(height(node->left), height(node->right));int balance = getBalance(node);// LL型失衡(直接右旋)if (balance > 1 && val < node->left->val)return rightRotate(node);// RR型失衡(直接左旋)if (balance < -1 && val > node->right->val)return leftRotate(node);// LR型失衡(先左旋左子树,再右旋当前节点)if (balance > 1 && val > node->left->val) {node->left = leftRotate(node->left);return rightRotate(node);}// RL型失衡(先右旋右子树,再左旋当前节点)if (balance < -1 && val < node->right->val) {node->right = rightRotate(node->right);return leftRotate(node);}return node;}// 递归删除实现AVLNode* remove(AVLNode* node, int val) {if (!node) return nullptr;// 1. 标准BST删除if (val < node->val) {node->left = remove(node->left, val);}else if (val > node->val) {node->right = remove(node->right, val);}else {// 找到要删除的节点if (!node->left || !node->right) {AVLNode* temp = node->left ? node->left : node->right;if (!temp) { // 无子节点情况temp = node;node = nullptr;}else { // 单子节点情况delete node;return temp; }delete temp;}else { // 双子节点情况AVLNode* temp = minValueNode(node->right);node->val = temp->val;node->right = remove(node->right, temp->val);}}if (!node) return nullptr;// 2. 更新高度node->height = 1 + max(height(node->left), height(node->right));// 3. 检查平衡因子int balance = getBalance(node);// 4. 处理四种失衡情况(关键修改点)// 左左失衡if (balance > 1 && getBalance(node->left) >= 0)return rightRotate(node);// 左右失衡if (balance > 1 && getBalance(node->left) < 0) {node->left = leftRotate(node->left);return rightRotate(node);}// 右右失衡if (balance < -1 && getBalance(node->right) <= 0)return leftRotate(node);// 右左失衡if (balance < -1 && getBalance(node->right) > 0) {node->right = rightRotate(node->right);return leftRotate(node);}return node;}// 中序遍历实现void inOrder(AVLNode* node) {if (!node) return;inOrder(node->left);cout << node->val << " ";inOrder(node->right);}// 前序遍历实现void preOrder(AVLNode* node) {if (!node) return;cout << node->val << " ";preOrder(node->left);preOrder(node->right);}// 搜索功能实现bool search(AVLNode* node, int val) {if (!node) return false;if (val < node->val) return search(node->left, val);if (val > node->val) return search(node->right, val);return true;}};// 测试用例
void testAVLTree() {AVLTree tree;// LL型失衡测试cout << "LL型失衡测试:" << endl;int ll_test[] = { 30, 20, 10 };for (int num : ll_test) {tree.insert(num);}cout << "中序遍历结果: ";tree.inOrder();cout << "层序遍历结果: " << endl;tree.printLevelOrder();// 清空树tree = AVLTree();// RR型失衡测试cout << "\nRR型失衡测试:" << endl;int rr_test[] = { 10, 20, 30 };for (int num : rr_test) {tree.insert(num);}cout << "中序遍历结果: ";tree.inOrder();cout << "层序遍历结果: " << endl;tree.printLevelOrder();// 清空树tree = AVLTree();// LR型失衡测试cout << "\nLR型失衡测试:" << endl;int lr_test[] = { 30, 10, 20 };for (int num : lr_test) {tree.insert(num);}cout << "中序遍历结果: ";tree.inOrder();cout << "层序遍历结果: " << endl;tree.printLevelOrder();// 清空树tree = AVLTree();// RL型失衡测试cout << "\nRL型失衡测试:" << endl;int rl_test[] = { 10, 30, 20 };for (int num : rl_test) {tree.insert(num);}cout << "中序遍历结果: ";tree.inOrder();cout << "层序遍历结果: " << endl;tree.printLevelOrder();
}int main() {testAVLTree();return 0;
}
代码说明
1. LL型失衡(左左失衡)- 右旋操作

插入序列: 30, 20, 10

插入30: 30插入20:30/
20插入10后(失衡):       右旋后:30             20/              /  \20      →      10    30/10
2. RR型失衡(右右失衡)- 左旋操作

插入序列: 10, 20, 30

插入10:
10插入20:10\20插入30后(失衡):       左旋后:10                  20\                /  \20      →     10    30\30
3. LR型失衡(左右失衡)- 先左旋子树再右旋

插入序列: 30, 10, 20

插入30:30插入10:30/
10插入20后(失衡):      左旋子树后:        右旋根节点后:30                30                 20/                 /                  /  \10        →       20         →       10    30\               /20           10
4. RL型失衡(右左失衡)- 先右旋子树再左旋

插入序列: 10, 30, 20

插入10:
10插入30:10\30插入20后(失衡):      右旋子树后:        左旋根节点后:10                  10                  20\                  \                 /  \30       →         20      →      10    30/                     \20                      30
测试用例输出
LL型失衡测试:
中序遍历结果: 10 20 30 
层序遍历结果: 
20 
10 30 RR型失衡测试:
中序遍历结果: 10 20 30 
层序遍历结果: 
20 
10 30 LR型失衡测试:
中序遍历结果: 10 20 30 
层序遍历结果: 
20 
10 30 RL型失衡测试:
中序遍历结果: 10 20 30 
层序遍历结果: 
20 
10 30 

7、典型应用场景

  1. 数据库索引:MySQL的MEMORY存储引擎
  2. 文件系统:Windows NT内核的地址空间管理
  3. 内存受限系统:嵌入式设备的快速查询
  4. 3D图形计算:场景图的空间划分管理

三、哈夫曼树(Huffman Tree)


1. 哈夫曼树定义

哈夫曼树(Huffman Tree),又称最优二叉树,是一种带权路径长度(WPL, Weighted Path Length)最短的二叉树。

其特点是:

  • 带权路径最小:叶子节点的权值(如字符频率)乘以路径长度(根到叶子的边数)的总和最小。

  • 应用场景:广泛用于数据压缩,如哈夫曼编码,通过为高频字符分配短编码、低频字符分配长编码,减少整体数据量。

  • 核心特性:权重越大的叶子节点距离根节点越近。

  • 核心应用:数据压缩(哈夫曼编码)、文件编码、加密算法等。


2. 哈夫曼树构建过程

以权值集合 {5, 9, 12, 13, 16, 45} 为例:

  1. 初始化森林

    将每个权值视为独立的单节点树,组成森林:
    [5], [9], [12], [13], [16], [45]

  2. 合并最小两子树

    • 第1次合并:选择最小权值 59,生成父节点 14
      森林更新:[14], [12], [13], [16], [45]
    • 第2次合并:选择 1213,生成父节点 25
      森林更新:[14], [16], [25], [45]
    • 第3次合并:选择 1416,生成父节点 30
      森林更新:[25], [30], [45]
    • 第4次合并:选择 2530,生成父节点 55
      森林更新:[45], [55]
    • 第5次合并:合并 4555,生成父节点 100
      最终得到哈夫曼树,根节点权值为 100
  3. 验证特性

    • WPL计算(5+9)*3 + (12+13+16)*2 + 45*1 = 146
    • 权重越大越靠近根:最大权值 45 直接作为根的子节点。

3. 树结构流程图

5
9
12
13
14
16
25
30
45
55
100

流程图说明:

  1. 根节点权值为 100(所有原始权值之和:5+9+12+13+16+45)。
  2. 叶子节点为原始权值,内部节点为合并生成的权值。
  3. 路径关系:父节点到子节点的连接体现合并顺序。

5. 代码实现

#include <iostream>
#include <queue>
#include <vector>
using namespace std;// 哈夫曼树节点定义
struct HuffmanNode {int weight;HuffmanNode *left, *right;HuffmanNode(int w) : weight(w), left(nullptr), right(nullptr) {}
};// 优先队列比较规则(最小堆)
struct Compare {bool operator()(HuffmanNode* a, HuffmanNode* b) {return a->weight > b->weight;}
};// 构建哈夫曼树函数
HuffmanNode* buildHuffmanTree(vector<int>& weights) {priority_queue<HuffmanNode*, vector<HuffmanNode*>, Compare> minHeap;// 初始化所有单节点树for (int w : weights) {minHeap.push(new HuffmanNode(w));}// 循环合并最小两树while (minHeap.size() > 1) {HuffmanNode* left = minHeap.top();minHeap.pop();HuffmanNode* right = minHeap.top();minHeap.pop();HuffmanNode* parent = new HuffmanNode(left->weight + right->weight);parent->left = left;parent->right = right;minHeap.push(parent);}return minHeap.empty() ? nullptr : minHeap.top();
}// 辅助函数:打印先序遍历结果
void printHuffmanTree(HuffmanNode* root) {if (!root) return;cout << root->weight << " ";printHuffmanTree(root->left);printHuffmanTree(root->right);
}int main() {vector<int> weights = {5, 9, 12, 13, 16, 45};HuffmanNode* root = buildHuffmanTree(weights);cout << "哈夫曼树先序遍历(权值):";printHuffmanTree(root);  // 输出示例:100 45 55 25 12 13 30 14 5 9 16return 0;
}

6. 关键特性总结

特性说明
时间复杂度O(n log n),优先队列操作主导
空间复杂度O(n),存储所有节点
唯一性同一权值集合可能有不同形态的哈夫曼树,但WPL一定最小
验证方法根节点权值等于初始权值总和,且权重大的节点靠近根


四、红黑树(Red-Black Tree)


1. 什么是红黑树

红黑树是一种自平衡的二叉搜索树(BST),通过颜色属性维护树的平衡性,确保插入、删除、查找的最坏时间复杂度为 O(log n)

核心性质:

  1. 颜色属性:每个节点是红色或黑色。
  2. 根节点:根节点必须为黑色。
  3. 叶子节点:所有叶子(NIL节点,空节点)为黑色。
  4. 红色节点规则:红色节点的子节点必须为黑色(即不能有连续红色节点)。
  5. 黑高一致:从任意节点到其所有叶子节点的路径上,黑色节点的数量相同。

2. 红黑树插入

插入新节点时默认设为红色(避免破坏黑高),可能违反红黑树规则,需通过旋转和颜色调整修复。

插入步骤:

  1. 标准BST插入:按二叉搜索树规则插入节点,颜色设为红色。
  2. 颜色修复
    • Case 1:父节点是黑色 → 无需调整。
    • Case 2:父节点是红色 → 需要进一步判断叔叔节点颜色:
      • 叔叔为红色:父和叔变黑,祖父变红,递归处理祖父节点。
      • 叔叔为黑色或NIL
        • LL/RR型:单旋转(父节点上升,祖父下沉)。
        • LR/RL型:双旋转(先子节点旋转,再父节点旋转)。

示例(插入后修复连续红色冲突):

G:黑
P:红
U:红
新节点:红

修复操作:将P和U变黑,G变红,然后以G为起点继续检查。


3. 红黑树删除

删除节点可能导致黑高被破坏,需通过旋转和颜色调整修复。

删除步骤:

  1. 标准BST删除:找到待删除节点,若有两个子节点则用后继节点替代。
  2. 颜色修复
    • 若删除节点是红色 → 直接删除,无需调整。
    • 若删除节点是黑色 → 需从兄弟节点“借”黑色或调整颜色。

修复策略(设当前节点为N,父为P,兄弟为S):

  • Case 1:S为红色 → 旋转使S变黑,转化为其他情况。
  • Case 2:S为黑色,且S的子节点均为黑色 → S变红,N上移至P递归处理。
  • Case 3:S为黑色,且S的远子节点为红色 → 旋转并重新着色,恢复平衡。
  • Case 4:S为黑色,且S的近子节点为红色 → 旋转调整,转为Case 3。

示例(删除黑色节点后的修复):

P:黑
N:黑
S:红
SL:黑
SR:黑

修复操作:旋转使S成为新的父节点,并调整颜色。


4. 红黑树实现

#include <iostream>
using namespace std;enum Color { RED, BLACK };struct Node {int val;Color color;Node* left, * right, * parent;Node(int v) : val(v), color(RED), left(nullptr), right(nullptr), parent(nullptr) {}
};class RedBlackTree {
private:Node* root;Node* nil; // 哨兵节点(代表NIL叶子节点)// 初始化哨兵节点void initializeNil() {nil = new Node(0);nil->color = BLACK;nil->left = nil->right = nil->parent = nullptr;}// 左旋void leftRotate(Node* x) {Node* y = x->right;x->right = y->left;if (y->left != nil) y->left->parent = x;y->parent = x->parent;if (x->parent == nil) {root = y;}else if (x == x->parent->left) {x->parent->left = y;}else {x->parent->right = y;}y->left = x;x->parent = y;}// 右旋void rightRotate(Node* x) {Node* y = x->left;x->left = y->right;if (y->right != nil) y->right->parent = x;y->parent = x->parent;if (x->parent == nil) {root = y;}else if (x == x->parent->right) {x->parent->right = y;}else {x->parent->left = y;}y->right = x;x->parent = y;}// 插入修复void fixInsert(Node* z) {while (z->parent->color == RED) {if (z->parent == z->parent->parent->left) { // 父节点是左孩子Node* y = z->parent->parent->right; // 叔叔节点if (y->color == RED) { // Case 1: 叔叔为红z->parent->color = BLACK;y->color = BLACK;z->parent->parent->color = RED;z = z->parent->parent;}else {if (z == z->parent->right) { // Case 2: z是右孩子,转Case3z = z->parent;leftRotate(z);}// Case 3: z是左孩子z->parent->color = BLACK;z->parent->parent->color = RED;rightRotate(z->parent->parent);}}else { // 对称处理父节点是右孩子的情况Node* y = z->parent->parent->left;if (y->color == RED) {z->parent->color = BLACK;y->color = BLACK;z->parent->parent->color = RED;z = z->parent->parent;}else {if (z == z->parent->left) {z = z->parent;rightRotate(z);}z->parent->color = BLACK;z->parent->parent->color = RED;leftRotate(z->parent->parent);}}}root->color = BLACK;}// 删除修复void fixDelete(Node* x) {while (x != root && x->color == BLACK) {if (x == x->parent->left) {Node* w = x->parent->right; // 兄弟节点if (w->color == RED) { // Case 1: 兄弟为红w->color = BLACK;x->parent->color = RED;leftRotate(x->parent);w = x->parent->right;}if (w->left->color == BLACK && w->right->color == BLACK) { // Case 2w->color = RED;x = x->parent;}else {if (w->right->color == BLACK) { // Case 3: 兄弟的右子为黑w->left->color = BLACK;w->color = RED;rightRotate(w);w = x->parent->right;}// Case 4: 兄弟的右子为红w->color = x->parent->color;x->parent->color = BLACK;w->right->color = BLACK;leftRotate(x->parent);x = root;}}else { // 对称处理x是右孩子的情况Node* w = x->parent->left;if (w->color == RED) {w->color = BLACK;x->parent->color = RED;rightRotate(x->parent);w = x->parent->left;}if (w->right->color == BLACK && w->left->color == BLACK) {w->color = RED;x = x->parent;}else {if (w->left->color == BLACK) {w->right->color = BLACK;w->color = RED;leftRotate(w);w = x->parent->left;}w->color = x->parent->color;x->parent->color = BLACK;w->left->color = BLACK;rightRotate(x->parent);x = root;}}}x->color = BLACK;}// 辅助函数:用v替换u的父节点连接void transplant(Node* u, Node* v) {if (u->parent == nil) {root = v;}else if (u == u->parent->left) {u->parent->left = v;}else {u->parent->right = v;}v->parent = u->parent;}// 找到最小节点Node* minimum(Node* node) {while (node->left != nil) {node = node->left;}return node;}public:RedBlackTree() {initializeNil();root = nil;}// 查找节点Node* search(int val) {Node* current = root;while (current != nil) {if (val == current->val) return current;else if (val < current->val) current = current->left;else current = current->right;}return nil;}// 插入节点void insert(int val) {Node* z = new Node(val);Node* y = nil;Node* x = root;while (x != nil) {y = x;if (z->val < x->val) x = x->left;else x = x->right;}z->parent = y;if (y == nil) {root = z;}else if (z->val < y->val) {y->left = z;}else {y->right = z;}z->left = z->right = nil;z->color = RED;fixInsert(z);}// 删除节点void deleteNode(int val) {Node* z = search(val);if (z == nil) return;Node* y = z;Color yOriginalColor = y->color;Node* x;if (z->left == nil) {x = z->right;transplant(z, z->right);}else if (z->right == nil) {x = z->left;transplant(z, z->left);}else {y = minimum(z->right);yOriginalColor = y->color;x = y->right;if (y->parent == z) {x->parent = y;}else {transplant(y, y->right);y->right = z->right;y->right->parent = y;}transplant(z, y);y->left = z->left;y->left->parent = y;y->color = z->color;}delete z;if (yOriginalColor == BLACK) {fixDelete(x);}}// 中序遍历(测试用)void inorder(Node* node) {if (node != nil) {inorder(node->left);cout << node->val << "(" << (node->color == RED ? "R" : "B") << ") ";inorder(node->right);}}void printTree() {inorder(root);cout << endl;}
};// 测试代码
int main() {RedBlackTree rbt;rbt.insert(10);rbt.insert(20);rbt.insert(5);rbt.insert(15);rbt.insert(25);cout << "插入后: ";rbt.printTree();rbt.deleteNode(15);cout << "删除15后: ";rbt.printTree();rbt.deleteNode(10);cout << "删除10后: ";rbt.printTree();return 0;
} 
测试用例输出
插入后: 5(B) 10(B) 15(R) 20(B) 25(R)
删除15后: 5(B) 10(B) 20(B) 25(R)
删除10后: 5(B) 20(B) 25(B)

红黑树结构流程图
  1. 插入操作后(10,20,5,15,25)
        10(B)/     \5(B)     20(B)/     \15(R)   25(R)
  • 根节点:10(黑色)
  • 20的左子节点:15(红色)
  • 20的右子节点:25(红色)
  • 所有叶子节点(nil)均为黑色

  1. 删除15(红色叶子节点)后
        10(B)/     \5(B)     20(B)\25(R)
  • 15被删除,20的右子树仅剩25(红色)
  • 无需调整颜色/旋转(删除红色节点不破坏性质)

  1. 删除10(根节点)后
        20(B)/     \5(B)     25(B)
  • 根节点替换为20,颜色保持原黑色
  • 5和25调整为黑色(保持黑高平衡)

5. 红黑树特性总结

特性说明
平衡性通过颜色和旋转规则保证树高近似 log n,避免BST退化成链表
时间复杂度插入、删除、查找均为 O(log n)
应用场景C++ STL的map/set,Java的TreeMap,数据库索引等
与AVL树对比红黑树插入/删除更快(旋转次数少),AVL查询更快(更严格平衡)

五、B,B+,B*树

B树族核心概念对比

特性B树B+树B*树
数据存储位置所有节点存储数据仅叶子节点存储数据仅叶子节点存储数据
叶子节点链接有双向链表连接所有叶子节点有双向链表连接所有叶子节点
非叶节点键数量m/2 ≤ keys ≤ mm/2 ≤ keys ≤ m(2m-1)/3 ≤ keys ≤ m
节点分裂策略直接分裂分裂时向兄弟节点借数据分裂时与兄弟节点共享数据
空间利用率约50%约50%约66%
适用场景文件系统数据库索引高并发数据库系统
B*树
子节点1
非叶节点
键数下限更高
子节点2
叶子节点
存储数据
共享键区域
B+树
子节点1
非叶节点
仅存储键
子节点2
叶子节点
存储数据
双向链表连接
叶子节点
存储数据
双向链表连接
B树
子节点1
非叶节点
存储键和数据
子节点2
数据块
数据块

1. B树

B树(B-Tree) 是一种自平衡的多路搜索树,广泛应用于数据库和文件系统。其核心特性如下:

非叶节点
键: 20, 40
数据: D1, D2
子节点
键: 10,15
数据: D3,D4
子节点
键: 25,30
数据: D5,D6
子节点
键: 50,60
数据: D7,D8
  • 阶数:B树的阶数 m 表示每个节点最多拥有 m 个子节点。
  • 键数量:每个节点最多包含:m - 1 个键,最少包含 ⌈m/2⌉ - 1 个键(根节点除外)。
  • 平衡性:所有叶子节点位于同一层,保证查询效率稳定。
  • 操作:插入和删除可能引发节点分裂或合并,通过递归调整保持平衡。

2. B+树

B+树 是B树的变体,优化了范围查询:

双向链表
双向链表
非叶节点
键: 20, 40
叶子节点
键: 10,15,20
数据: D1,D2,D3
叶子节点
键: 25,30,40
数据: D4,D5,D6
叶子节点
键: 50,60,70
数据: D7,D8,D9
  • 数据存储:所有数据仅存于叶子节点,内部节点仅存键和子节点指针。
  • 链表连接:叶子节点通过指针形成有序链表,便于遍历区间数据。
  • 查询特性:查询必须到叶子节点,但内部节点更紧凑,树高更低。

3. B*树

B*树 进一步优化空间利用率:

共享键
共享键
节点A
键: 10,20,30
子节点B
子节点C
新节点D
  • 节点分裂策略:节点满时,优先将部分键转移至兄弟节点,延迟分裂。
  • 填充率:节点最小键数从 ⌈m/2⌉ 提高至 ⌈2m/3⌉,减少空间浪费。

4. B树实现

4. B树的C++实现

以下为简化版B树实现(仅插入和查找):

#include <iostream>
using namespace std;class BTree {
private:struct Node {int *keys;Node **children;int num_keys;bool is_leaf;int t;  // 最小度数Node(int degree, bool leaf) : t(degree), is_leaf(leaf), num_keys(0) {keys = new int[2 * t - 1];children = new Node*[2 * t]();}~Node() {delete[] keys;for (int i = 0; i <= 2 * t; ++i) delete children[i];delete[] children;}};Node *root;int t;  // 最小度数void splitChild(Node *parent, int idx) {Node *fullChild = parent->children[idx];Node *newChild = new Node(t, fullChild->is_leaf);newChild->num_keys = t - 1;// 复制后t-1个键和子节点for (int i = 0; i < t - 1; ++i)newChild->keys[i] = fullChild->keys[i + t];if (!fullChild->is_leaf)for (int i = 0; i < t; ++i)newChild->children[i] = fullChild->children[i + t];fullChild->num_keys = t - 1;// 调整父节点for (int i = parent->num_keys; i > idx; --i)parent->keys[i] = parent->keys[i - 1];for (int i = parent->num_keys + 1; i > idx + 1; --i)parent->children[i] = parent->children[i - 1];parent->keys[idx] = fullChild->keys[t - 1];parent->children[idx + 1] = newChild;parent->num_keys++;}void insertNonFull(Node *node, int key) {int i = node->num_keys - 1;if (node->is_leaf) {while (i >= 0 && key < node->keys[i]) {node->keys[i + 1] = node->keys[i];i--;}node->keys[i + 1] = key;node->num_keys++;} else {while (i >= 0 && key < node->keys[i]) i--;i++;if (node->children[i]->num_keys == 2 * t - 1) {splitChild(node, i);if (key > node->keys[i]) i++;}insertNonFull(node->children[i], key);}}public:BTree(int degree) : t(degree), root(nullptr) {}void insert(int key) {if (!root) {root = new Node(t, true);root->keys[0] = key;root->num_keys = 1;} else {if (root->num_keys == 2 * t - 1) {Node *newRoot = new Node(t, false);newRoot->children[0] = root;splitChild(newRoot, 0);root = newRoot;}insertNonFull(root, key);}}bool search(int key) {return search(root, key);}bool search(Node *node, int key) {if (!node) return false;int i = 0;while (i < node->num_keys && key > node->keys[i]) i++;if (i < node->num_keys && key == node->keys[i]) return true;return node->is_leaf ? false : search(node->children[i], key);}
};int main() {BTree t(3); // 最小度数t=3t.insert(10);t.insert(20);t.insert(5);t.insert(6);t.insert(12);cout << (t.search(6) ? "Found" : "Not Found") << endl; // Foundcout << (t.search(15) ? "Found" : "Not Found") << endl; // Not Foundreturn 0;
}

代码解析

  • 节点结构:每个节点包含键数组、子节点指针数组、键数量及叶子标记。
  • 插入逻辑:根节点满时先分裂,确保插入始终从非满节点开始。
  • 分裂操作:满子节点分裂为二,中间键提升至父节点。
  • 查找逻辑:递归遍历节点,逐层比较键值。

相关文章:

数据结构之BST、AVL、红黑树、哈夫曼树与B族树

数据结构之BST、AVL、红黑树、哈夫曼树与B族树 数据结构之BST、AVL、红黑树、哈夫曼树与B族树一、二叉搜索树&#xff08;Binary Search Tree, BST&#xff09;1. 什么是二叉搜索树&#xff1f;重要性质 2. 二叉搜索树实现1. 节点结构定义2. 核心操作接口3. 插入算法实现4. 删除…...

开源多商户商城源码最新版_适配微信小程序+H5+APP+PC多端

在数字化时代&#xff0c;电子商务已经成为各行业不可或缺的一部分&#xff0c;开源多商户商城源码为中小企业和个人开发者提供了快速搭建和定制电商平台的利器。分享一款最新版的开源多商户商城源码&#xff0c;它能够适配微信小程序、H5、APP和PC等多个端口&#xff0c;满足商…...

第3章 .NETCore核心基础组件:3.1 .NET Core依赖注入

3.1.1 什么是控制反转、依赖注入 杨老师在书中进行了一系列的文字阐述&#xff0c;总结一下就是&#xff1a;软件设计模式中有一种叫做【控制反转】的设计模式&#xff0c;而依赖注入是实现这种设计模式的一个很重要的方式。也就是说学习依赖注入&#xff0c;是学习怎样实现控…...

cesium基础设置

cesium官网下载&#xff1a;https://cesium.com/downloads/ 1.安装cesium 选择下载到本地使用&#xff0c;或者通过npm下载到项目中 2.代码书写 &#xff08;1&#xff09;创建容器 <div id"cesiumContainer" style"width: 100%; height: 100%"><…...

Spring-GPT智谱清言AI项目(附源码)

一、项目介绍 本项目是Spring AI第三方调用整合智谱请言&#xff08;官网是&#xff1a;https://open.bigmodel.cn&#xff09;的案例&#xff0c;回答响应流式输出显示&#xff0c;这里使用的是免费模型&#xff0c;需要其他模型可以去 https://www.bigmodel.cn/pricing 切换…...

文件夹上传到github分支最后github上面还是没有文件和文件夹

环境&#xff1a; github 问题描述&#xff1a; 文件夹上传到github分支最后github上面还是没有文件和文件夹, 和这样一样 解决方案&#xff1a; 从 git ls-tree -r HEAD 的输出中可以看到&#xff0c;metahuman-stream 文件夹显示为如下内容&#xff1a; 160000 commi…...

面试题之箭头函数和普通函数有什么区别?

箭头函数&#xff08;Arrow Function&#xff09;和普通函数&#xff08;Regular Function&#xff09;是 JavaScript 中两种不同的函数定义方式&#xff0c;它们在语法、上下文&#xff08;this&#xff09;、原型链等方面存在显著区别。以下是它们的主要区别&#xff1a; 1. …...

【文献精读】AAAI24:FacetCRS:打破对话推荐系统中的“信息茧房”

标题FacetCRS: Multi-Faceted Preference Learning for Pricking Filter Bubbles in Conversational Recommender System期刊The Thirty-Eighth AAAI Conference on Artificial Intelligence (AAAI-24)年份2024关键词Conversational Recommender System (CRS), Filter Bubbles,…...

[vs2017][qt]MSB4019 未找到导入的项目QtMsBuild\Qt.prop

问题场景&#xff1a; vs2017qt5.9.9新建vs项目报错MSB4019 未找到导入的项目QtMsBuild\Qt.prop 报错解决方案&#xff1a; 由QtMsBuild导致的问题不需要像其他博客里说的那样各种环境变量配置&#xff0c;以及大费周章去查看一些系统的东西。 第一步&#xff1a; 只需要将…...

网络安全推荐的视频教程 网络安全系列

第一章 网络安全概述 1.2.1 网络安全概念P4 网络安全是指网络系统的硬件、软件及其系统中的数据受到保护&#xff0c;不因偶然的或恶意的原因而遭到破坏、更改、泄露&#xff0c;系统连续可靠正常地运行&#xff0c;网络服务不中断。 1.2.3 网络安全的种类P5 &#xff08;1…...

什么是Embedding、RAG、Function calling、Prompt engineering、Langchain、向量数据库? 怎么使用

什么是Embedding、RAG、Function calling、Prompt engineering、Langchain、向量数据库? 怎么使用 目录 什么是Embedding、RAG、Function calling、Prompt engineering、Langchain、向量数据库? 怎么使用Embedding(嵌入)RAG(检索增强生成)Function calling(函数调用)Pr…...

基于Python的深度学习音乐推荐系统(有配套论文)

音乐推荐系统 提供实时音乐推荐功能&#xff0c;根据用户行为和偏好动态调整推荐内容 Python、Django、深度学习、卷积神经网络 、算法 数据库&#xff1a;MySQL 系统包含角色&#xff1a;管理员、用户 管理员功能&#xff1a;用户管理、系统设置、音乐管理、音乐推荐管理、系…...

长文档处理痛点:GPT-4 Turbo引文提取优化策略与替代方案讨论

引言 随着GPT-4 Turbo的发布&#xff0c;其支持的128K上下文窗口&#xff08;约300页文本&#xff09;被视为处理长文本的突破性升级。然而&#xff0c;实际应用中&#xff0c;用户发现模型在提取长文档中的引文时存在显著缺陷&#xff1a;文档前三分之一的引文数量远多于中间…...

javacv将mp4视频切分为m3u8视频并播放

学习链接 ffmpeg-demo 当前对应的 gitee代码 Spring boot视频播放(解决MP4大文件无法播放)&#xff0c;整合ffmpeg,用m3u8切片播放。 springboot 通过javaCV 实现mp4转m3u8 上传oss 如何保护会员或付费视频&#xff1f;优酷是怎么做的&#xff1f; - HLS 流媒体加密 ffmpe…...

Swagger 转 Word 技术方案

项目概述 本项目旨在提供一种便捷的工具,将 Swagger API 文档转换为 Word 文档,方便开发人员和团队进行文档管理和分享。通过简单的配置和操作,用户可以快速生成包含 API 接口信息、请求参数、返回参数等内容的 Word 文档。 技术架构 本项目基于 Java 开发,采用 Spring …...

MVTEC数据集笔记

前言 网上的博客只有从论文里摘出的介绍&#xff0c;没有数据集文件详细的样子&#xff0c;下载数据集之后&#xff0c;对数据集具体的构成做一个补充的笔记。 下载链接&#xff1a;https://ai-studio-online.bj.bcebos.com/v1/7d4a3cf558254bbaaf4778ea336cb14ed8bbb96a7f2a…...

[数据结构]红黑树,详细图解插入

目录 一、红黑树的概念 二、红黑树的性质 三、红黑树节点的定义 四、红黑树的插入&#xff08;步骤&#xff09; 1.为什么新插入的节点必须给红色&#xff1f; 2、插入红色节点后&#xff0c;判定红黑树性质是否被破坏 五、插入出现连续红节点情况分析图解&#xff08;看…...

国家地理信息公共服务平台的天地图

文章目录 一、国家地理信息公共服务平台的天地图二、地图转换1.GIS数据格式坐标转换&#xff08;地球坐标WGS84、GCJ-02、火星坐标、百度坐标BD-09、国家大地坐标系CGCS2000&#xff09;2.读入数据 总结 一、国家地理信息公共服务平台的天地图 三大地图付费后&#xff0c;仍可…...

【ISO 14229-1:2023 UDS诊断(会话控制0x10服务)测试用例CAPL代码全解析⑤】

ISO 14229-1:2023 UDS诊断【会话控制0x10服务】_TestCase05 作者&#xff1a;车端域控测试工程师 更新日期&#xff1a;2025年02月15日 关键词&#xff1a;UDS诊断、0x10服务、诊断会话控制、ECU测试、ISO 14229-1:2023 TC10-005测试用例 用例ID测试场景验证要点参考条款预期…...

JavaScript中字符串的常用方法

JavaScript中字符串的常用方法 1.查询类2.拼接3.截取4.大小写5.去掉空格6.重复7.填充8.分隔9.模版匹配方法 可以通过查看String对象的原型来看有哪些方法: console.dir(String.prototype)1.查询类 charAt(index):返回指定位字符 console.log("abc".charAt(1));//b…...

python和pycharm 和Anaconda的关系

好的&#xff0c;下面我会详细说明 Python、PyCharm 和 Anaconda 三者的关系&#xff0c;并逐一解释它们的功能和作用。 1. Python&#xff08;编程语言&#xff09; 定义&#xff1a;Python 是一种高级编程语言&#xff0c;设计简洁&#xff0c;易于学习&#xff0c;且功能强…...

CMake 判断 Mac编译环境是Intel的还是Arm的?

在 CMake 中判断 Mac 是 Intel 架构还是 ARM 架构&#xff0c;可以通过检测 CMAKE_SYSTEM_PROCESSOR 变量。这个变量返回的是系统的处理器架构信息&#xff0c;可以根据它的值来区分 Intel 和 ARM。 具体来说&#xff1a; 对于 Intel Mac&#xff0c;CMAKE_SYSTEM_PROCESSOR …...

基于fastadmin快速搭建导航站和API接口站点系统源码

源码介绍 基于fastadmin快速搭建导航站和API接口站点系统源码 上传源码 设置运行目录为/public 导入 数据库.sql到数据库 设置配置文件application/database.php 后台admin.php 可以自己随意修改本文件名称为后台地址 推荐越复杂越好 账号admin 密码 123456 效果预览...

【Vue3】Vue 3 中列表排序的优化技巧

本文将深入探讨 Vue 3 中列表排序的优化技巧&#xff0c;帮助提升应用的性能和响应速度。 1. 避免不必要的排序 按需排序 在实际应用中&#xff0c;并非每次数据更新都需要进行排序。例如&#xff0c;当列表数据仅在特定条件下需要排序时&#xff0c;可通过条件判断来避免不…...

【Github每日推荐】-- 2024 年项目汇总

1、AI 技术 项目简述OmniParser一款基于纯视觉的 GUI 智能体&#xff0c;能够准确识别界面上可交互图标以及理解截图中各元素语义&#xff0c;实现自动化界面交互场景&#xff0c;如自动化测试、自动化操作等。ChatTTS一款专门为对话场景设计的语音生成模型&#xff0c;主要用…...

在C#中动态访问对象属性时,用表达式树可以获得高效性能

在C#中如何用表达式树动态访问对象属性的问题。用户可能已经知道反射的基本用法&#xff0c;但想用表达式树来提高性能&#xff0c;因为表达式树编译后的委托执行速度比反射快。 首先&#xff0c;表达式树的基本概念。表达式树允许在运行时构建代码&#xff0c;并编译成可执行的…...

Nginx实战_高性能Web服务器与反向代理的配置全解

1. 引言 1.1 Nginx简介 Nginx(发音为 “engine-x”)是一款轻量级、高性能的HTTP服务器和反向代理服务器。它以其高并发处理能力和低资源消耗而闻名,广泛应用于互联网企业中。Nginx不仅可以作为静态文件服务器,还可以通过反向代理功能与后端应用服务器协同工作。 1.2 Ngi…...

使用html css js 来实现一个服装行业的企业站源码-静态网站模板

最近在练习 前端基础&#xff0c;html css 和js 为了加强 代码的 熟悉程序&#xff0c;就使用 前端 写了一个个服装行业的企业站。把使用的技术 和 页面效果分享给大家。 应用场景 该制衣服装工厂官网前端静态网站模板主要用于前端练习和编程练习&#xff0c;适合初学者进行 HT…...

Flutter 网络请求与数据处理:从基础到单例封装

Flutter 网络请求与数据处理&#xff1a;从基础到单例封装 在 Flutter 开发中&#xff0c;网络请求是一个非常常见的需求&#xff0c;比如获取 API 数据、上传文件、处理分页加载等。为了高效地处理网络请求和数据管理&#xff0c;我们需要选择合适的工具并进行合理的封装。 …...

数控机床设备分布式健康监测与智能维护系统MTAgent

数控机床设备分布式健康监测与智能维护系统MTAgent-v1.1融合了目前各种先进的信号处理以及信息分析算法以算法工具箱的方式&#xff0c;采用了一种开发的、模块化的结构实现信号各种分析处理&#xff0c;采用Python编程语言&#xff0c;满足不同平台需求(包括Windows、Linux)。…...