【C++】模拟实现一颗二叉搜索树
❤️欢迎来到我的博客❤️ |
前言
搜索二叉树是在二叉树的基础上加了一个特征:左子树的所有节点都小于根,右子树的所有节点都大于根(每一颗子树都要满足)
因为这个特性的存在,使得他特别擅长搜索数据
比如我要寻找10,如果当前根为6,比10小,根据这个特征我们就可以排除左子树的节点(都是比6小的数),直接去右子树中寻找
如果当前根为11,比10大,那么我们就可以排除右子树当中所有的数据,直接去左子树中寻找
搜索二叉树也叫二叉搜索树、二叉排序树:当搜索二叉树走中序遍历,他就是一个有序的状态->左->根->右
时间复杂度
以上都是二叉搜索树,但他们的时间复杂度却是不一样的,所以时间复杂度为最多找高度次(最坏的情况):O(N)
后续的AVL树和红黑树都是针对这种情况做出的优化:O(logN)
二叉搜索树的模拟实现
整体框架 / insert / inorder
普通二叉树的增删查改是没有价值的,因为数据没有固定的插入位置,所以普通二叉树可以用链表替代
但是二叉搜索树插入的数据就有意义了,因为他们需要插入到他们需要到的位置
插入模式:
比如我们要插入一个11,那我们的顺序就是:根->右->右->左->左插入
如果要插入一个13,顺序是:根->右->右->左,发现已经存在13(目前阶段不允许出现重复数据),插入失败
插入一个16,那我们的顺序就是:根->右->右->右插入
#include <iostream>
using namespace std;template<class K>
struct BSTreeNode
{BSTreeNode<K>* _left; // 左子节点指针BSTreeNode<K>* _right; // 右子节点指针K _key; // 节点存储的键值BSTreeNode(const K& key):_left(nullptr),_right(nullptr),_key(key){ }
};template<class K>
class BSTree
{typedef BSTreeNode<K> Node;
public:BSTree():_root(nullptr){ }bool Insert(const K& key){//如果是空树if (_root == nullptr){//直接new一个_root = new Node(key);return true;}//循环插入版本Node* parent = nullptr;Node* cur = _root;//如果cur不为空,则去找位置while (cur){// 当前节点值 < 插入值 → 向右子树查找if (cur->_key < key){// 记录父节点parent = cur;//走右子树cur = cur->_right;}else if (cur->_key > key) // 当前节点值 > 插入值 → 向左子树查找{// 记录父节点parent = cur;//走左子树cur = cur->_left;}else{//如果值存在则插入失败return false;}}//走到指定位置cur = new Node(key);// 判断插入方向if (parent->_key < key){parent->_right = cur;}else{parent->_left = cur;}return true;}//类外面拿不到私有成员//单独写一个函数来调用void InOrder(){_InOrder(_root);}//中序遍历void _InOrder(Node* root){if (root == nullptr){return;}// 递归中序遍历_InOrder(root->_left); //左cout << root->_key << " "; //根_InOrder(root->_right); //右}
private:Node* _root; // 根节点指针
};int main()
{int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };BSTree<int> t;for (auto e : a){t.Insert(e);}t.InOrder();// 输出:1 3 4 6 7 8 10 13 14(有序验证BST正确性)return 0;
}
运行结果:
查找
bool Find(const K& key)
{Node* cur = _root;// 从根节点开始查找while (cur){if (cur->_key < key)// 目标值 > 当前节点 → 向右子树查找{cur = cur->_right;}else if (cur->_key > key)// 目标值 < 当前节点 → 向左子树查找{cur = cur->_left;}else{return true; // 找到目标值 → 返回存在}}return false;
}int main()
{int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };BSTree<int> t;for (auto e : a){t.Insert(e);}cout << t.Find(13) << endl;cout << t.Find(15) << endl;return 0;
}
运行结果:
删除
如果我们要删除7,是属于直接删除的场景,实现起来比较容易(特征:没有孩子)
如果要删除14,也是比较好实现的删除之后,只需要链接一下即可(特征:只有一个孩子)
但是如果我们要删除的是8呢,那要考虑的就多了(特征:两个孩子)这时候就要用替换法(左子树的最大节点(最右节点),或者右子树的最小节点(最左节点))来实现
bool Erase(const K& key)
{Node* parent = nullptr; // 记录当前节点的父节点Node* cur = _root; // 从根节点开始查找//查找while (cur){//使用Find函数做起来会比较麻烦//不考虑服用Findif (cur->_key < key) // 目标值在右子树{parent = cur;cur = cur->_right;}else if (cur->_key > key) // 目标值在左子树{parent = cur;cur = cur->_left;}else //找到了{//情况1:左子树为空(含叶子节点)if (cur->_left == nullptr){//处理根节点情况if (cur == _root){// 根指向右子树_root = cur->_right;}else{// 判断当前节点是父节点的左/右孩子if (parent->_right == cur){parent->_right = cur->_right;}else{parent->_left = cur->_right;}}}//情况2:右子树为空else if (cur->_right == nullptr){if (cur == _root){_root = cur->_left;}else{if (parent->_right == cur){parent->_right = cur->_left;}else{parent->_left = cur->_left;}}}//情况3:左右子树均不为空(替换法)else{// 查找左子树最大节点作为替代节点Node* parent = cur; // 记录替代节点的父节点Node* leftMax = cur->_left; // 进入左子树// 一直向右找到最右节点(左子树最大值)while (leftMax->_right){parent = leftMax;leftMax = leftMax->_right;}// 交换当前节点与替代节点的值swap(cur->_key, leftMax->_key);// 删除替代节点(此时maxLeft右子树必为空)if (parent->_left == leftMax){// 若替代节点是父的左孩子,链接其左子树parent->_left = leftMax->_left;}else{// 若替代节点是父的右孩子,链接其左子树parent->_right = leftMax->_left;}cur = leftMax;}delete cur; // 释放替代节点return true; // 删除成功}}return false; // 未找到目标节点
}int main()
{int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };BSTree<int> t;for (auto e : a){t.Insert(e);}t.InOrder();t.Erase(4);t.InOrder();t.Erase(6);t.InOrder();t.Erase(7);t.InOrder();//删空for (auto e : a){t.Erase(e);}cout << "当前树:";t.InOrder();return 0;
}
运行结果:
删除总结
首先查找元素是否在二叉搜索树中,如果不存在,则返回, 否则要删除的结点可能分下面四种情况:
a. 要删除的结点无孩子结点
b. 要删除的结点只有左孩子结点
c. 要删除的结点只有右孩子结点
d. 要删除的结点有左、右孩子结点
实际情况a可以与情况b或者c合并起来,因此真正的删除过程
如下:
情况b:删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点–直接删除
情况c:删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点–直接删除
情况d:在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点中,再来处理该结点的删除问题–替换法删除
删除逻辑分布解析
二叉搜索树删除操作分步解析
1. 查找待删除节点
核心逻辑:从根节点出发,根据BST特性向左或向右搜索目标值。
终止条件:
- 找到目标节点(
cur->_key == key
) - 遍历到空节点(
cur == nullptr
),说明目标不存在
2. 处理删除的三种情况
情况1:左子树为空
特征:待删节点无左孩子(可能为叶子节点或仅有右子树)
操作步骤:
-
根节点处理:
- 若删除的是根节点,直接让根指向右子树
_root = cur->_right;
-
非根节点处理:
- 若待删节点是父节点的右孩子:
parent->_right = cur->_right;
- 若待删节点是父节点的左孩子:
parent->_left = cur->_right;
情况2:右子树为空
特征:待删节点无右孩子(仅有左子树)
操作步骤(与情况1对称):
- 根节点处理:
_root = cur->_left;
2.非根节点处理:
- 若待删节点是父节点的右孩子:
parent->_right = cur->_left;
- 若待删节点是父节点的左孩子:
- parent->_left = cur->_left;
情况3:左右子树均不为空
核心思想:找到替代节点替换待删节点的值,再删除替代节点
步骤详解:
步骤1:查找替代节点:两种方案选一即可
方案一:左子树最大节点
Node* parent = cur; // 记录替代节点的父节点
Node* leftMax = cur->_left; // 进入左子树// 一直向右找到最右节点(左子树最大值)
while (leftMax->_right)
{parent = leftMax;leftMax = leftMax->_right;
}
方案二:右子树最小节点
Node* minParent = cur; // 初始化替代节点的父节点为当前节点
Node* minRight = cur->_right; // 进入右子树// 找到右子树的最左节点(最小值节点)
while (minRight->_left)
{ minParent = minRight;minRight = minRight->_left;
}
步骤2:值替换
// 交换当前节点与替代节点的值
swap(cur->_key, leftMax->_key);
步骤3:删除替代节点
// 删除替代节点(此时maxLeft右子树必为空)
if (parent->_left == leftMax)
{// 若替代节点是父的左孩子,链接其左子树parent->_left = leftMax->_left;
}
else
{// 若替代节点是父的右孩子,链接其左子树parent->_right = leftMax->_left;
}cur = leftMax;
递归版本
#include <iostream>
using namespace std;template<class K>
struct BSTreeNode
{BSTreeNode<K>* _left; // 左子节点指针BSTreeNode<K>* _right; // 右子节点指针K _key; // 节点存储的键值BSTreeNode(const K& key):_left(nullptr), _right(nullptr), _key(key){}
};template<class K>
class BSTree
{typedef BSTreeNode<K> Node;
public:BSTree():_root(nullptr){}BSTree(const BSTree<K>& t){_root = Copy(t._root);}BSTree<K>& operator=(BSTree<K> t){swap(_root, t._root);return *this;}~BSTree(){Destroy(_root);}void InOrder(){_InOrder(_root);cout << endl;}// 递归查找入口函数bool FindR(const K& key){return _FindR(_root, key);}// 递归插入入口函数bool InsertR(const K& key){return _InsertR(_root, key);}// 递归删除入口函数bool EraseR(const K& key){return _EraseR(_root, key);}private:// 递归删除实现(参数为节点指针的引用,确保树结构正确更新)bool _EraseR(Node*& root, const K& key){if (root == nullptr){return false; // 空树或遍历到叶子未找到目标节点}if (root->_key < key){return _EraseR(root->_right, key);// 递归右子树查找}else if (root->_key > key){return _EraseR(root->_left, key);// 递归左子树查找}else// 找到目标节点{Node* del = root;//1、左为空//2、右为空//3、左右都不为空if (root->_left == nullptr) //左子树为空{root = root->_right; // 直接让父节点指针指向右子树}else if (root->_right == nullptr) //右子树为空{root = root->_left; //直接让父节点指针指向左子树}else //左右子树均非空{Node* leftMax = root->_left; //找到左子树最大节点(最右节点)while (leftMax->_right){leftMax = leftMax->_right;}swap(root->_key, leftMax->_key);//交换当前节点与左子树最大节点的键值return _EraseR(root->_left, key);//递归删除左子树中的原最大节点}delete del;return true;}}//递归插入实现(参数为节点指针的引用,确保树结构正确更新)bool _InsertR(Node*& root, const K& key){if (root == nullptr){root = new Node(key); //创建新节点并链接到父节点return true;}if (root->_key < key){return _InsertR(root->_right, key); // 递归右子树插入}else if (root->_key > key){return _InsertR(root->_left, key); //递归左子树插入}else{return false;}}//递归查找实现bool _FindR(Node* root, const K& key){if (root == nullptr)return false;if (root->_key < key){return _FindR(root->_right, key);//递归右子树查找}else if (root->_key > key){return _FindR(root->_left, key); //递归左子树查找}else{return true;}}//中序遍历void _InOrder(Node* root){if (root == nullptr){return;}// 递归中序遍历_InOrder(root->_left); //左cout << root->_key << " "; //根_InOrder(root->_right); //右}Node* _root; //根节点指针
};int main()
{int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };BSTree<int> t;for (auto e : a){t.InsertR(e);}t.InOrder();t.EraseR(4);t.InOrder();t.EraseR(6);t.InOrder();t.EraseR(7);t.InOrder();t.EraseR(3);t.InOrder();for (auto e : a){t.EraseR(e);}t.InOrder();return 0;
}
运行结果:
Copy和Destroy
#include <iostream>
using namespace std;template<class K>
struct BSTreeNode
{BSTreeNode<K>* _left; // 左子节点指针BSTreeNode<K>* _right; // 右子节点指针K _key; // 节点存储的键值BSTreeNode(const K& key):_left(nullptr), _right(nullptr), _key(key){}
};template<class K>
class BSTree
{typedef BSTreeNode<K> Node;
public:BSTree():_root(nullptr){}BSTree(const BSTree<K>& t){_root = Copy(t._root);}BSTree<K>& operator=(BSTree<K> t){swap(_root, t._root);return *this;}~BSTree(){Destroy(_root);}
private:Node* Copy(Node* root){//递归终止条件if (root == nullptr){return nullptr;}//创建当前节点的副本(深拷贝键值)Node* copyroot = new Node(root->_key);//递归拷贝左子树,并正确链接到副本节点的左指针copyroot->_left = Copy(root->_left);//递归拷贝右子树,并正确链接到副本节点的右指针copyroot->_right = Copy(root->_right);//返回当前子树副本的根节点return copyroot;}void Destroy(Node*& root) {//递归终止条件:当前节点为空,无需处理if (root == nullptr) {return;}//递归销毁左子树Destroy(root->_left);//递归销毁右子树Destroy(root->_right);//释放当前节点内存delete root;//将当前指针置空root = nullptr;}
};
key / value模型
节点结构:
每个节点包含Key、Value和左右子节点指针
排序规则:
树的结构依然基于key 的大小关系维护,value不参与运算
左子树所有节点的key < 当前节点的key
右子树所有节点的key > 当前节点的key
namespace key_value
{template<class K, class V>struct BSTreeNode{BSTreeNode<K, V>* _left;BSTreeNode<K, V>* _right;K _key;V _value;BSTreeNode(const K& key, const V& value):_left(nullptr), _right(nullptr), _key(key), _value(value){}};template<class K, class V>class BSTree{typedef BSTreeNode<K, V> Node;public:BSTree():_root(nullptr){}void InOrder(){_InOrder(_root);cout << endl;}Node* FindR(const K& key){return _FindR(_root, key);}bool InsertR(const K& key, const V& value){return _InsertR(_root, key, value);}bool EraseR(const K& key){return _EraseR(_root, key);}private:bool _EraseR(Node*& root, const K& key){if (root == nullptr)return false;if (root->_key < key){return _EraseR(root->_right, key);}else if (root->_key > key){return _EraseR(root->_left, key);}else{Node* del = root;if (root->_left == nullptr){root = root->_right;}else if (root->_right == nullptr){root = root->_left;}else{Node* leftMax = root->_left;while (leftMax->_right){leftMax = leftMax->_right;}swap(root->_key, leftMax->_key);return _EraseR(root->_left, key);}delete del;return true;}}bool _InsertR(Node*& root, const K& key, const V& value){if (root == nullptr){root = new Node(key, value);return true;}if (root->_key < key){return _InsertR(root->_right, key, value);}else if (root->_key > key){return _InsertR(root->_left, key, value);}else{return false;}}Node* _FindR(Node* root, const K& key){if (root == nullptr)return nullptr;if (root->_key < key){return _FindR(root->_right, key);}else if (root->_key > key){return _FindR(root->_left, key);}else{return root;}}void _InOrder(Node* root){if (root == NULL){return;}_InOrder(root->_left);cout << root->_key << ":" << root->_value << endl;_InOrder(root->_right);}private:Node* _root;};}int main()
{key_value::BSTree<string, string> dict;dict.InsertR("insert", "插入");dict.InsertR("sort", "排序");dict.InsertR("right", "右边");dict.InsertR("date", "日期");string str;while (cin >> str){auto ret = dict.FindR(str);if (ret){cout << ret->_value << endl;}else{cout << "无此单词" << endl;}}return 0;
}
运行效果:
统计次数场景
修改后的InOrder:
void _InOrder(Node* root)
{if (root == NULL){return;}_InOrder(root->_left);cout << root->_key << ":" << root->_value << endl;_InOrder(root->_right);
}
int main()
{//统计水果出现的次数string arr[] = { "西瓜", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };key_value::BSTree<string, int> countTree;//遍历水果for (auto& str : arr){//在树中查找当前水果名称对应的节点auto ret = countTree.FindR(str);// 情况1:水果未存在于树中(首次出现)if (ret == nullptr){//插入新节点:为水果名,初始次数为1countTree.InsertR(str, 1);}else// 情况2:水果已存在于树中{//递增该水果的计数ret->_value++;}}//次数统计完成,遍历这棵树countTree.InOrder();return 0;
}
运行结果:
以上就是本篇文章的全部内容了,希望大家看完能有所收获
❤️创作不易,点个赞吧❤️ |
相关文章:
【C++】模拟实现一颗二叉搜索树
❤️欢迎来到我的博客❤️ 前言 搜索二叉树是在二叉树的基础上加了一个特征:左子树的所有节点都小于根,右子树的所有节点都大于根(每一颗子树都要满足) 因为这个特性的存在,使得他特别擅长搜索数据 比如我要寻找10&a…...
vue 点击放大,图片预览效果
背景: 在vue框架element组件的背景下,我们对图片点击放大(单张);如果是多张图片,要支持左右滑动查看多张图片(多张)。 图片单张放大,el-image图片组件,或者原生的img标签。previewSrcList string[单个] 图片…...
AI知识补全(七):AI Agent 智能代理是什么?
名人说:人生如逆旅,我亦是行人。 ——苏轼《临江仙送钱穆父》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 上一篇:AI知识补全(六):RLHF 人类反馈…...
Java 中各种锁的使用详解
Java 锁的使用详解 Java 提供了多种锁机制来处理并发编程中的同步问题。下面我将通过代码示例来展示各种锁的使用方法和特点。 锁的选择指南 以下是选择合适锁的指南: 基本锁类型演示 // 由于这是在 Node.js 环境中模拟 Java 锁的概念,我们将使用注释…...
【GreenHills】GHS解决客户端在连接的时候提示在黑名单
1、 文档目标 解决GHS网络版客户在客户端连接的时候出现黑名单的问题 2、 问题场景 用于解决GHS的网络版客户在搭建完服务端后,客户端去连接服务的时候出现提示“在黑名单中”等情况(如图2-1和图2-2)。但是在服务器上面并没有设置黑名单。 …...
智能运维时代的网络拓扑管理:乐维监控的架构可视化实践
在数字化转型的浪潮中,企业IT基础设施正经历着前所未有的复杂化进程。当数以千计的网络设备、服务器、存储系统构成庞大网络体系时,如何实现全局可视化管理已成为企业数字化转型的关键命题。乐维监控网络拓扑系统作为新一代智能运维平台的核心组件&#…...
GitHub美化个人主页3D图表显示配置操作
这个功能主要是用的这个开源仓库:https://github.com/yoshi389111/github-profile-3d-contrib 想看效果的话,我的个人主页:https://github.com/Sjj1024 开始操作 1.创建自己的github主页属性项目——跟你github用户名一致即可,…...
Arduino示例代码讲解:Serial Event example 连续事件例子
Arduino示例代码讲解:Serial Event example 连续事件例子 Serial Event example 连续事件例子功能概述硬件部分:软件部分:代码逐行解释定义变量`setup()` 函数`loop()` 函数`serialEvent()` 函数工作原理Serial Event example 连续事件例子 这段代码是一个Arduino示例程序,…...
Java基础关键_031_反射(一)
目 录 一、概述 二、获取 Class 的三种方式 1.Class.forName("完整全限定类名") 2.getClass() 3.class 属性 三、通过反射机制实例化对象 1.newInstance()(已过时) 2.配置文件利用反射机制实例化对象 四、反射 Class 的 Field 1.获取 P…...
verilog/systemverilog中的位序问题
verilog或者systemverilog中在使用位选择时,必须按照定义的大小端顺序进行位选操作,比如定义了reg [11:0] data,在使用data的中间4位时,必须使用data[7:4],不能使用data[4:7]。 如下示例: module tb;reg […...
JVM考古现场(十三):混沌重启——从量子永生到宇宙热寂的终极编译
开篇:鸿蒙初判熵火燎原"诸君可曾窥见《诛仙剑阵》终章里那冻结的量子递归?当Project Omega的热寂算法冰封时空熵增,当意识编译器的玻尔兹曼大脑撕裂熵障,此刻我们将踏碎归墟晶壁,在第十三维度叩问:从代…...
CARLA常见技术问题集锦(一)地图与场景构建篇
编者荐语: 在自动驾驶技术加速落地的今天,CARLA 仿真引擎凭借其开源生态与高保真仿真能力,已成为全球开发者构建智能驾驶算法的核心工具之一。随着虚幻引擎 5.5 的全面升级,CARLA 0.10.0 版本实现了视觉革命:Lumen 全…...
视图、MySQL、触发器、存储过程、流程控制语句
DAY19.1 Java核心基础 MySQL 视图 数据库中的一张虚拟的表,允许不同用户和不同程序以不同的方式查询同一张表的数据 基于数据表,创建一个虚拟的表,然后可以选择需要展示的字段 为不同的用户创建不同的视图,一个视图包含薪资&…...
多层感知机(MLP)全面指南
多层感知机(MLP) 是一种人工神经网络,由多个神经元层组成。MLP中的神经元通常使用非线性激活函数,使得网络能够学习数据中的复杂模式。MLP 在机器学习中非常重要,因为它能够学习数据中的非线性关系,使其成为分类、回归和模式识别等任务中的强大模型。 神经网络基础 神经…...
【第13届蓝桥杯C/C++B组省赛】顺子日期
答案:14 1.数组办法解决 思路:前四个元素已经确定,分别枚举其他元素的合法性 #include <stdio.h> int main() {int a[8] {2,0,2,0,0,0,0,0};int month[13]{0,31,28,31,30,31,30,31,31,30,31,30,31};int i,j;int count 0;for(i 1;…...
智慧医疗胃癌检测数据集VOC+YOLO格式487张2类别
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):487 标注数量(xml文件个数):487 标注数量(txt文件个数):487 标注…...
每日一题-力扣-2716: 最小化字符串长度 0328
LeetCode 2716: 最小化字符串长度问题剖析 题目解读 LeetCode 2716 是一道关于字符串操作的算法题。这道题乍看复杂,实则蕴含着优雅的数学规律。题目要求通过一系列特定的删除操作来最小化字符串的长度: 给定一个下标从 0 开始的字符串 s每次操作可以选…...
量子计算:开启未来计算的新纪元
一、引言 在当今数字化时代,计算技术的飞速发展深刻地改变了我们的生活和工作方式。从传统的电子计算机到如今的高性能超级计算机,人类在计算能力上取得了巨大的进步。然而,随着科技的不断推进,我们面临着越来越多的复杂问题&…...
安卓车载app面经
java部分 常见集合类 List 继承了Collection接口的一个接口,List中的数据是有序的,可重复的 实现类 在Java中,List 是一个接口,它属于 Java Collections Framework 的一部分。List 接口代表了一个有序的集合(有时…...
JAVA SE :认识数组
目录 1.概念 2.数组的创建和初始化 2.1 创建 2.2 初始化 3.数组的使用 4.认识引用数据类型 4.1 JVM的内存分布 4.2 基本数据类型和引用数据类型 4.3 null的认识 5.二维数组 6.Arrays类的了解和使用 1.概念 数组用于存储一定数量相同类型的数据,可以看…...
深入理解机器学习之TF-IDF:文本特征提取的核心技术
文章目录 引言一、什么是TF-IDF?二、TF-IDF的数学原理1. 词频(TF)计算2. 逆文档频率(IDF)计算3. TF-IDF计算 三、TF-IDF的Python实现1.数据文件介绍2.导入库3.读取数据4.数据预处理5.对单词进行排序6.全部代码 四、结语 引言 在自然语言处理(NLP)和文本挖掘领域&am…...
Anaconda Jupyter 默认启动位置修改
Anaconda Jupyter 默认启动位置修改 本篇给大家分享的事关于Anaconda Jupyter的保存路径修改方法。 我们使用Anaconda Jupyter默认启动时,通常会跳转进入C盘的用户目录下,如下图所示。 但是很多时候我们使用 Jupyter 的场景并不在C盘,因为它…...
CNG汽车加气站操作工备考真题及答案解析【判断题】
1、燃气经营许可证按照燃气经营规模和类别实行分级审批。(√) 解析:不同规模和类别的燃气经营,其许可证审批级别不同,以确保经营活动的规范和安全。 2、依照《安全生产法》的规定,安全生产监督检查人员对检…...
es 3期 第27节-运用Script脚本实现复杂需求
#### 1.Elasticsearch是数据库,不是普通的Java应用程序,传统数据库需要的硬件资源同样需要,提升性能最有效的就是升级硬件。 #### 2.Elasticsearch是文档型数据库,不是关系型数据库,不具备严格的ACID事务特性ÿ…...
智能监控视频聚合平台,GB28181/RTSP/SIP/RTMP直播会议融合方案
全场景智能监控聚合平台:打破边界,赋能高效协同 在数字化转型加速的今天,海量视频监控设备、多样化的编码协议与复杂的业务场景,让企业面临跨系统整合难、资源调度效率低、协作响应慢等痛点。我们的智能监控聚合平台以技术创新为…...
B494:开关电源领域的PWM控制新星
在电子技术飞速发展的今天,高效的电源管理系统成为各类电子设备稳定运行的关键。B494电压驱动型脉宽调制(PWM)控制集成电路以其卓越的性能和丰富的功能,成为开关电源设计领域的焦点。 一、B494:开关电源领域的PWM控制…...
03 相机标定图像采集
学完本文,您将获取一下技能: 1:如何提升标定质量,如选择标定板,标定图像采集的注意事项, 2:实现标定图像自动筛选的代码 3:量产场景如何通过一张图像来标定相机 为了实现良好的标定效果,以下因素在标定数据采集前必须设置得当。 标定板选择 标定板尺寸准确材料平…...
详解Spark executor
在 Apache Spark 中,Executor(执行器) 是运行在集群工作节点(Worker Node)上的进程,负责执行具体的计算任务并管理数据。它是 Spark 分布式计算的核心组件之一,直接决定了任务的并行度和资源利用…...
约束文件SDC常用命令
约束文件SDC常用命令 定义时钟create_clock -name CLK-period 2 [get_ports_clk]告诉工具主时钟周期是2ns(频率500MHz),从clk端口输入 输入信号延迟set_input_delay 0.5 -clock CLK [get_ports data_in]数据进芯片前,外部电路已消耗0.5ns,综合要预留这段“堵车时间”。 输出…...
流量分析2
一,webshell流量 [GKCTF 2021]签到 先看协议分级,大部分是tcp,里面有http的基于的行文本数据占了很大的比重,看看里面有什么 过滤http的流量 点击一条流量,里面的内容进去后面有基于行的文本数据, 先解he…...
23种设计模式-组合(Composite)设计模式
组合设计模式 🚩什么是组合设计模式?🚩组合设计模式的特点🚩组合设计模式的结构🚩组合设计模式的优缺点🚩组合设计模式的Java实现🚩代码总结🚩总结 🚩什么是组合设计模式…...
数据库概述
文章目录 数据库1、什么是数据库?2、数据库的分类关系型数据库非关系型数据库优缺点 3、MySQL数据库的安装和使用3.1 卸载3.2 安装命令行操作 4、 Navicat For MySQL连接MySQL新建数据库新建表在表中添加数据执行SQL语句 数据库 1、什么是数据库? 数据…...
C# System.Text.Encoding 使用详解
总目录 前言 在C#编程中,处理字符串和字节数组之间的转换是一个常见的任务。System.Text.Encoding类及其派生类提供了丰富的功能,帮助开发者实现不同字符编码之间的转换。本文将详细讲解System.Text.Encoding类的使用方法,包括常用编码的介绍…...
js 对象深拷贝的五种方法
js 对象深拷贝 今天遇到一个bug ,子组件页面修改了内容,但是按了取消保存按钮,没有将数据传回父组件的,但是父组件的数据改了,原因是通过子组件接受父组件的参数对象层级深没有做深拷贝的原因。 在 JavaScript 中&…...
1.1 计算机网络的概念
首先来看什么是计算机网络,关于计算机网络的定义并没有一个统一的标准,不同的教材有 不同的说法(这是王道书对于计算机网络的定义),我们可以结合自己的生活经验去体会这个 定义。 可以用不同类型的设备去连接计算机网络…...
当EFISH-SBC-RK3576遇上区块链:物联网安全与可信数据网络
在工业物联网场景中,设备身份伪造与数据篡改是核心安全隐患。EFISH-SBC-RK3576 通过 硬件安全模块 区块链链上验证,实现设备身份可信锚定与数据全生命周期加密,安全性能提升10倍以上。 1. 安全架构:从芯片到链的端到端防…...
k8s 基础知识:Service + 负载均衡(下)
但凡觉得哪块说有问题,欢迎评论区留言探讨,谢谢 K8s Service 是 Kubernetes 集群中用于暴露应用程序的一种资源对象: 一、概念与作用: Service 可以将一组具有相同功能的 Pod(容器组)定义为一个逻辑分组…...
deepseek(2)——deepseek 关键技术
1 Multi-Head Latent Attention (MLA) MLA的核心在于通过低秩联合压缩来减少注意力键(keys)和值(values)在推理过程中的缓存,从而提高推理效率: c t K V W D K V h t c_t^{KV} W^{DKV}h_t ctKVWDKVht…...
机器学习之条件概率
1. 引言 概率模型在机器学习中广泛应用于数据分析、模式识别和推理任务。本文将调研几种重要的概率模型,包括EM算法、MCMC、朴素贝叶斯、贝叶斯网络、概率图模型(CRF、HMM)以及最大熵模型,介绍其基本原理、算法流程、应用场景及优势。 2. EM算法(Expectation-Maximizati…...
第四天 文件操作(文本/CSV/JSON) - 异常处理机制 - 练习:日志文件分析器
Python文件操作与异常处理完全指南:从入门到实战 一、为什么要学习文件操作和异常处理? 在Python编程的初级阶段,我们主要处理内存中的数据。但当我们需要: 永久保存数据处理各种格式的数据文件分析系统日志构建数据处理管道 …...
多onnx模型导出合并调研(文本检测+方向分类+文本识别)
👑主页:吾名招财 👓简介:工科学硕,研究方向机器视觉,爱好较广泛… 💫签名:面朝大海,春暖花开! 多onnx模型合并导出调研(文本检测+方向分类+文本识别) 引言1,尝试合并两个模型(文本方向分类+文本识别模型)(并行合并)(1)文本方向分类(2)文本识别模型(…...
linux scp复制多层级文件夹到另一服务器免密及脚本配置
文章目录 生成 SSH 密钥对将公钥复制到目标服务器验证免密登录scp 多级文件夹复制脚本 生成 SSH 密钥对 在本地机器上,使用 ssh-keygen 命令生成 SSH 密钥对。打开终端并执行以下命令: ssh-keygen -t rsa 按提示连续按回车键,默认会在 ~/.ss…...
Ubuntu 22.04 安装向日葵远程控制
1. 前言 由于公司客户的服务器用是图形化桌面,所以我们需要一个远程控制工具来控制服务器,目前市面上两款比较热门的控制软件就是ToDesk和向日葵了,我们今天就来学习一下向日葵的使用 2. 下载软件 前往向日葵官网下载 向日葵远程控制app官…...
Spring Boot(十七):集成和使用Redis
Redis(Remote Dictionary Server,远程字典服务器)是一个开源的、基于内存的数据结构存储系统,它可以用作数据库、缓存和消息中间件。Spring Boot 中集成和使用Redis主要涉及以下几个步骤: 添加依赖 在项目的pom.xml文件中添加Redis的依赖。Spring Boot提供了对Redis的集…...
Redisson - 分布式锁和同步器
文章目录 锁(Lock)公平锁(Fair Lock)联锁(MultiLock)红锁(RedLock) 【已废弃】读写锁(ReadWriteLock)信号量(Semaphore)可过期许可信号…...
LabVIEW时间触发协议
介绍了基于LabVIEW开发的时间触发协议应用,通过实例解析了FlexRay总线的设计与优化。通过技术细节、系统构建和功能实现等方面,探讨了LabVIEW在现代工业通信系统中的应用效能,特别是在提高通信可靠性和实时性方面的贡献。 项目背景 在工…...
IDEA的使用
idea的介绍 IntelliJ IDEA 是由 JetBrains 公司开发的一款功能强大的集成开发环境(IDE),主要用于Java语言的开发,但同时也支持其他多种编程语言如Kotlin、Groovy、Scala等。它被广泛认为是专业软件开发者的首选工具之一ÿ…...
unity一个图片的物体,会有透明的效果
如图 想要去掉这个透明效果 选择一个高层级的layer即可。...
IP报文格式
IPv4 头部结构(共 20 字节,不含可选字段) 1. 版本(Version) 长度:4 比特 作用:标识 IP 协议版本(IPv4 值为 4,IPv6 值为 6)。 示例:0100&#x…...
2025最新-智慧小区物业管理系统
目录 1. 项目概述 2. 技术栈 3. 功能模块 3.1 管理员端 3.1.1 核心业务处理模块 3.1.2 基础信息模块 3.1.3 数据统计分析模块 3.2 业主端 5. 系统架构 5.1 前端架构 5.2 后端架构 5.3 数据交互流程 6. 部署说明 6.1 环境要求 6.2 部署步骤 7. 使用说明 7.1 管…...