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

二叉树搜索

✅<1>主页:我的代码爱吃辣
📃<2>知识讲解:数据结构——二叉搜索树
☂️<3>开发环境
:Visual Studio 2022
💬<4>前言:在之前的我们已经学过了普通二叉树,了解了基本的二叉树的结构和基本操作了,不过我们之前的二叉树结构都是使用C语言实现的,我们这次来介绍二叉树中更加复杂的树结构,C语言在实现这些结构已经有些吃力了,更适合我们使用C++来实现。

目录

一.前言

二.二叉搜索树

三. 二叉搜索树操作

1.结点与整体结构

2.insert()

 3.find()

4.erase()

 5.构造与析构

四.二叉搜索树的应用

 五. 二叉搜索树的性能分析

六.整体代码


一.前言

map和set特性需要先铺垫二叉搜索树,而二叉搜索树也是一种树形结构,二叉搜索树的特性了解,有助于更好的理解map和set的特性,二叉树中部分面试题稍微有点难度,在前面讲解大家不容易接受,且时间长容易忘。本节借二叉树搜索树,对二叉树部分进行收尾总结。

二.二叉搜索树

二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:

  • 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
  • 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
  • 它的左右子树也分别为二叉搜索树

三. 二叉搜索树操作

1.结点与整体结构

template<class K>
struct BSTreeNode
{BSTreeNode(K key):_key(key),_right(nullptr),_left(nullptr){}K _key;  //数值BSTreeNode<K>* _right;  //右孩子BSTreeNode<K>* _left;   //左孩子
};template<class K>
class BSTree 
{typedef BSTreeNode<K> Node;
public://...
private:Node* _root = nullptr;
};

2.insert()

我们主要针对两种情况:

  1. 二叉树中一个数据都没有
  2. 二叉树已经有数据了

如果二叉树中还没有数据,我们需要将插入的第一个数据作为二叉搜索树的根节点。

如果二叉搜索树中,已经有了数据,我们根据搜索二叉树的特性,如果插入的值比根小,我们就往根的左子树去插入,如果插入的值比根大,我们就往根的右子树去插入,如果遇到相同的值就算是插入失败了,循环上面得动作,直到找到一个空位置。

 循环版本:

    bool insert(const K& key){//如果BSTree还没有结点if (_root == nullptr){_root = new Node(key);return true;}//找到插入的合适位置,和其父亲结点//父亲结点得作用是,我们新插入得结点要和父亲结点连接,//简单来说就是,父亲结点要孩子指针,要指向我们新的结点。Node* cur = _root;Node* parent = nullptr;while (cur){if (key < cur->_key){parent = cur;cur = cur->_left;}else if (key > cur->_key){parent = cur;cur = cur->_right;}else{return false;}}//创建新节点cur = new Node(key);//判断新插入得结点是父亲得左孩子还是右孩子if (key > parent->_key){parent->_right = cur;}else{parent->_left = cur;}return true;}

递归版本:

   bool Rinsert(const K& key){return _Rinsert(_root, key);}bool _Rinsert(Node*& root, const K& key){//如果BSTree还没有结点、或者已经找到得合适的空位置if (root == nullptr){root = new Node(key);return true;}//BSTree已经有结点if (key < root->_key){//key比当前结点小,往左树插入return _Rinsert(root->_left, key);}else if (key > root->_key){//key比当前结点大,往右树插入return _Rinsert(root->_right, key);}else{return false;}}//中序遍历void InOrder(){_InOrder(_root);}void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);cout << root->_key << " " ;_InOrder(root->_right);}

测试:

二叉搜索树,中序遍历得结果就是排序结果,我们可以通过这个特性判断我们插入得是否正确。

int  main()
{int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };BSTree<int> b;BSTree<int> Rb;for (auto e : a){b.insert(e);Rb.Rinsert(e);}b.InOrder();cout << endl;Rb.InOrder();return 0;
}

 3.find()

二叉搜索树的查找

  1. 从根开始比较,查找,比根大则往右边走查找,比根小则往左边走查找。
  2. 最多查找高度次,走到到空,还没找到,这个值不存在。

找到以后返回目标结点得指针。

 

循环版本:

    Node* find(const K& key){Node* cur = _root;while (cur){if (key < cur->_key){cur = cur->_left;}else if (key > cur->_key){cur = cur->_right;}else{return cur;}}return nullptr;}

递归版本:

    Node* Rfind(const K& key){return _Rfind(_root, key);}Node* _Rfind(Node*& root, const K& key){if (root == nullptr){return nullptr;}if (key < root->_key){return _Rfind(root->_left, key);}else if (key > root->_key){return _Rfind(root->_right, key);}else{return root;}}

4.erase()

二叉搜索树的删除

首先查找元素是否在二叉搜索树中,如果不存在,则返回, 否要删除则的结点可能分下面四种情
况:

  • a. 要删除的结点无孩子结点
  • b. 要删除的结点只有左孩子结点
  • c. 要删除的结点只有右孩子结点
  • d. 要删除的结点有左、右孩子结点

看起来有待删除节点有4中情况,实际情况a可以与情况b或者c合并起来,因此真正的删除过程
如下:

  • 情况1:要删除的结点只有左孩子结点,删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点--直接删除
  • 情况2:要删除的结点只有右孩子结点,删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点--直接删除
  • 情况3:要删除的结点有左、右孩子结点,在它的右子树中寻找中序下的第一个结点(数值最小),用它的值填补到被删除节点中,再来处理该结点的删除问题--替换法删除

 情况二与情况一处理方法相同:

 循环版本:

bool erase(const K& key){Node* cur = _root;Node* parent = nullptr;while (cur){if (key < cur->_key){parent = cur;cur = cur->_left;}else if (key > cur->_key){parent = cur;cur = cur->_right;}else{//准备删除//待删除结点,左节点为空,将其右边结点交给父亲if (cur->_left == nullptr){//此时如果删除的是根节点需要改变根节点指向if (cur == _root){_root = _root->_right;}else{//判断待删除结点是父亲的左孩子还是右孩子if (cur == parent->_left){parent->_left = cur->_right;}else{parent->_right = cur->_right;}}delete cur;return true;}//待删除结点,左节点为空,将其左边结点交给父亲else if (cur->_right == nullptr){//此时如果删除的是根节点需要改变根节点指向if (cur == _root){_root = _root->_left;}else{//判断待删除结点是父亲的左孩子还是右孩子if (cur == parent->_left){parent->_left = cur->_left;}else{parent->_right = cur->_left;}}delete cur;return true;}	else{//由于删除的结点左右都有孩子//需要找一个能代替删除结点的位置结点,即比左子树大比右子树小//最适合的结点就是,左子树的最右结点(最大节点),右子树的最左节点(最小结点)Node* MinNode = cur->_right;Node* MinParent = cur;while (MinNode->_left){MinParent = MinNode;MinNode = MinNode->_left;}//先将MinNode结点的孩子交给他的父亲//注意:不能因为是找的最左边结点就因为MinNode结点一定是MinParent的左孩子if (MinParent->_left == MinNode){MinParent->_left = MinNode->_right;}else{MinParent->_right = MinNode->_right;}//将MinNode结点的值赋值给curcur->_key = MinNode->_key;delete MinNode;return true;}}}return false;}

递归版本:

bool _Rerase(Node*& root, const K& key){//空树、没有找到删除的结点if (root == nullptr){return false;}if (key < root->_key){//key比当前结点小,往左树删除return _Rerase(root->_left, key);}else if(key > root->_key){//key比当前结点小,往左树删除return _Rerase(root->_right, key);}else{//找到,开始删除Node* cur = root;if (root->_left == nullptr){//1.待删除结点,左孩子为空root = root->_right;}else if (root->_right == nullptr){//2.待删除结点,右孩子为空root = root->_left;}else//待删除结点,左右孩子都不为空{//找到左树的最大结点Node* maxleft = root->_left;while (maxleft->_right){maxleft = maxleft->_right;}//交换maxleft和待删除结点的Key值,//并再次转换成左树删除一个单孩子结点,复用上述情况一二的代码swap(maxleft->_key, root->_key);return _Rerase(root->_left, key);}delete cur;}}

测试:

int  main()
{int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };BSTree<int> b;BSTree<int> Rb;for (auto e : a){b.insert(e);Rb.Rinsert(e);}for (auto e : a){b.erase(e);b.InOrder();cout << endl;Rb.Rerase(e);Rb.InOrder();cout << endl;}return 0;
}

 5.构造与析构

拷贝构造:

前序创建结点,后续连接指向。

    BSTree(const BSTree<K>& root){_root = _copy(root._root);}Node* _copy(const Node* root){if (root == nullptr)return nullptr;Node* newnode = new Node(root->_key);newnode->_left = _copy(root->_left);newnode->_right = _copy(root->_right);return newnode;}

析构函数:

后续销毁结点

	~BSTree(){Destroy(_root);}void Destroy(Node* root){if (root == nullptr)return;Destroy(root->_left);Destroy(root->_right);delete root;}

默认构造:

如果我们写了拷贝构造,编译器就不会自己生成默认构造函数了,我们可以自己写一个默认构造函数,也可以强制编译器生成一个,但是默认构造只能有一个。

	//告诉编译器强制生成BSTree() = default;//自己写BSTree(){}

四.二叉搜索树的应用

1. K模型:K模型即只有key作为关键码,结构中只需要存储Key即可,关键码即为需要搜索到
的值。
比如:给一个单词word,判断该单词是否拼写正确,具体方式如下:
以词库中所有单词集合中的每个单词作为key,构建一棵二叉搜索树
在二叉搜索树中检索该单词是否存在,存在则拼写正确,不存在则拼写错误。
2. KV模型:每一个关键码key,都有与之对应的值Value,即<Key, Value>的键值对。该种方
式在现实生活中非常常见:
比如英汉词典就是英文与中文的对应关系,通过英文可以快速找到与其对应的中文,英
文单词与其对应的中文<word, chinese>就构成一种键值对;
再比如统计单词次数,统计成功后,给定单词就可快速找到其出现的次数,单词与其出
现次数就是<word, count>就构成一种键值对。

例如:我们将上述的代码改造成K/V结构:

template<class K,class V>
struct BSTreeNode
{BSTreeNode(const K& key, const V& val):_key(key),_val(val),_right(nullptr),_left(nullptr){}K _key;V _val;BSTreeNode<K,V>* _right;BSTreeNode<K,V>* _left;
};template<class K, class V >
class KV_BSTree
{typedef BSTreeNode<K,V> Node;
public:KV_BSTree() = default;KV_BSTree(const KV_BSTree<K,V>& root){_root = _copy(root._root);}~KV_BSTree(){//...}bool insert(const K& key,const V& val){//如果BSTree还没有结点if (_root == nullptr){_root = new Node(key,val);return true;}//找到插入的合适位置,和其父亲结点Node* cur = _root;Node* parent = nullptr;while (cur){if (key < cur->_key){parent = cur;cur = cur->_left;}else if (key > cur->_key){parent = cur;cur = cur->_right;}else{return false;}}//判断链接cur = new Node(key,val);if (key > parent->_key){parent->_right = cur;}else{parent->_left = cur;}return true;}Node* find(const K& key){//...}bool erase(const K& key){//...}void InOrder(){_InOrder(_root);}private:void Destroy(Node* root){//...}void _InOrder(Node* root){//...}Node* _root = nullptr;
};int main()
{string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜",
"苹果", "香蕉", "苹果", "香蕉" };KV_BSTree<string,int> b;for (auto e : arr){auto cur = b.find(e);if (cur == nullptr){b.insert(e, 1);}else{cur->_val++;}}b.InOrder();return 0;
}

 统计水果出现的次数:

 五. 二叉搜索树的性能分析

插入和删除操作都必须先查找,查找效率代表了二叉搜索树中各个操作的性能。

对有n个结点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二
叉搜索树的深度的函数,即结点越深,则比较次数越多。
但对于同一个关键码集合,如果各关键码插入的次序不同,可能得到不同结构的二叉搜索树:

最优情况下,二叉搜索树为完全二叉树(或者接近完全二叉树),其平均比较次数为:$log_2 N$
最差情况下,二叉搜索树退化为单支树(或者类似单支),其平均比较次数为:$\frac{N}{2}$
问题:如果退化成单支树,二叉搜索树的性能就失去了。那能否进行改进,不论按照什么次序插
入关键码,二叉搜索树的性能都能达到最优?那么我们后续章节学习的AVL树和红黑树就可以上
场了。

六.整体代码

BSTree.hpp


#pragma once
#include<iostream>
using namespace std;template<class K>
struct BSTreeNode
{BSTreeNode(const K& key):_key(key),_right(nullptr),_left(nullptr){}K _key;BSTreeNode<K>* _right;BSTreeNode<K>* _left;
};template<class K>
class BSTree 
{typedef BSTreeNode<K> Node;
public://告诉编译器强制生成BSTree() = default;//自己写//BSTree()//{//}BSTree(const BSTree<K>& root){_root = _copy(root._root);}~BSTree(){Destroy(_root);}bool insert(const K& key){//如果BSTree还没有结点if (_root == nullptr){_root = new Node(key);return true;}//找到插入的合适位置,和其父亲结点//父亲结点得作用是,我们新插入得结点要和父亲结点连接,//简单来说就是,父亲结点要孩子指针,要指向我们新的结点。Node* cur = _root;Node* parent = nullptr;while (cur){if (key < cur->_key){parent = cur;cur = cur->_left;}else if (key > cur->_key){parent = cur;cur = cur->_right;}else{return false;}}//创建新节点cur = new Node(key);//判断新插入得结点是父亲得左孩子还是右孩子if (key > parent->_key){parent->_right = cur;}else{parent->_left = cur;}return true;}Node* find(const K& key){Node* cur = _root;while (cur){if (key < cur->_key){cur = cur->_left;}else if (key > cur->_key){cur = cur->_right;}else{return cur;}}return nullptr;}bool erase(const K& key){Node* cur = _root;Node* parent = nullptr;while (cur){if (key < cur->_key){parent = cur;cur = cur->_left;}else if (key > cur->_key){parent = cur;cur = cur->_right;}else{//准备删除//待删除结点,左节点为空,将其右边结点交给父亲if (cur->_left == nullptr){//此时如果删除的是根节点需要改变根节点指向if (cur == _root){_root = _root->_right;}else{//判断待删除结点是父亲的左孩子还是右孩子if (cur == parent->_left){parent->_left = cur->_right;}else{parent->_right = cur->_right;}}delete cur;return true;}//待删除结点,左节点为空,将其左边结点交给父亲else if (cur->_right == nullptr){//此时如果删除的是根节点需要改变根节点指向if (cur == _root){_root = _root->_left;}else{//判断待删除结点是父亲的左孩子还是右孩子if (cur == parent->_left){parent->_left = cur->_left;}else{parent->_right = cur->_left;}}delete cur;return true;}	else{//由于删除的结点左右都有孩子//需要找一个能代替删除结点的位置结点,即比左子树大比右子树小//最适合的结点就是,左子树的最右结点(最大节点),右子树的最左节点(最小结点)Node* MinNode = cur->_right;Node* MinParent = cur;while (MinNode->_left){MinParent = MinNode;MinNode = MinNode->_left;}//先将MinNode结点的孩子交给他的父亲//注意:不能因为是找的最左边结点就因为MinNode结点一定是MinParent的左孩子if (MinParent->_left == MinNode){MinParent->_left = MinNode->_right;}else{MinParent->_right = MinNode->_right;}//将MinNode结点的值赋值给curcur->_key = MinNode->_key;delete MinNode;return true;}}}return false;}bool Rerase(const K& key){return _Rerase(_root,key);}Node* Rfind(const K& key){return _Rfind(_root, key);}bool Rinsert(const K& key){return _Rinsert(_root, key);}void InOrder(){_InOrder(_root);}private:Node* _copy(const Node* root){if (root == nullptr)return nullptr;Node* newnode = new Node(root->_key);newnode->_left = _copy(root->_left);newnode->_right = _copy(root->_right);return newnode;}void Destroy(Node* root){if (root == nullptr)return;Destroy(root->_left);Destroy(root->_right);delete root;}bool _Rerase(Node*& root, const K& key){//空树、没有找到删除的结点if (root == nullptr){return false;}if (key < root->_key){//key比当前结点小,往左树删除return _Rerase(root->_left, key);}else if(key > root->_key){//key比当前结点小,往左树删除return _Rerase(root->_right, key);}else{//找到,开始删除Node* cur = root;if (root->_left == nullptr){//1.待删除结点,左孩子为空root = root->_right;}else if (root->_right == nullptr){//2.待删除结点,右孩子为空root = root->_left;}else//待删除结点,左右孩子都不为空{//找到左树的最大结点Node* maxleft = root->_left;while (maxleft->_right){maxleft = maxleft->_right;}//交换maxleft和待删除结点的Key值,//并再次转换成左树删除一个单孩子结点,复用上述情况一二的代码swap(maxleft->_key, root->_key);return _Rerase(root->_left, key);}delete cur;}}Node* _Rfind(Node*& root, const K& key){if (root == nullptr){return nullptr;}if (key < root->_key){return _Rfind(root->_left, key);}else if (key > root->_key){return _Rfind(root->_right, key);}else{return root;}}bool _Rinsert(Node*& root, const K& key){//如果BSTree还没有结点if (root == nullptr){root = new Node(key);return true;}//BSTree已经有结点if (key < root->_key){//key比当前结点小,往左树插入return _Rinsert(root->_left, key);}else if (key > root->_key){//key比当前结点大,往右树插入return _Rinsert(root->_right, key);}else{return false;}}void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);cout << root->_key << " " ;_InOrder(root->_right);}Node* _root = nullptr;
};

相关文章:

二叉树搜索

✅<1>主页&#xff1a;我的代码爱吃辣&#x1f4c3;<2>知识讲解&#xff1a;数据结构——二叉搜索树☂️<3>开发环境 &#xff1a;Visual Studio 2022&#x1f4ac;<4>前言&#xff1a;在之前的我们已经学过了普通二叉树&#xff0c;了解了基本的二叉树…...

【先进PID控制算法(ADRC,TD,ESO)加入永磁同步电机发电控制仿真模型研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

k8s集群生产环境的问题处理

2 k8s上的服务均无法访问 执行命令kubectl get pods -ALL,k8s集群中的服务均是running状态 1 kuboard 网页无法访问 kuboard无法通过浏览器访问&#xff0c;但是查看端口是被占用的...

serve : 无法将“serve”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。

1、在学习webpack打包的时候&#xff0c;需要 serve用来启动开发服务器来部署代码查看效果的。安装完之后运行出现以下错误&#xff1a; 2、使用命令查看安装目录&#xff1a; npm list -g我们已经安装过了 3、解决&#xff1a; 我们看到上图路径在&#xff1a;C:\Users\qiy…...

【LVS】2、部署LVS-DR群集

LVS-DR数据包的流向分析 1.客户端发送请求到负载均衡器&#xff0c;请求的数据报文到达内核空间&#xff1b; 2.负载均衡服务器和正式服务器在同一个网络中&#xff0c;数据通过二层数据链路层来传输&#xff1b; 3.内核空间判断数据包的目标IP是本机VIP&#xff0c;此时IP虚…...

设计模式 -- 单例模式(传统面向对象与JavaScript 的对比实现)

单例模式 – 传统面向对象与JavaScript 的对比实现 文章目录 单例模式 -- 传统面向对象与JavaScript 的对比实现传统的面向对象的实现定义实现思路初级实现缺点 透明的单例模式实现目的&#xff08;实现效果&#xff09;实现缺点 用代理实现单例模式优点 JavaScript 中的单例模…...

YOLOX算法调试记录

YOLOX是在YOLOv3基础上改进而来&#xff0c;具有与YOLOv5相媲美的性能&#xff0c;其模型结构如下&#xff1a; 由于博主只是要用YOLOX做对比试验&#xff0c;因此并不需要对模型的结构太过了解。 先前博主调试过YOLOv5,YOLOv7&#xff0c;YOLOv8,相比而言&#xff0c;YOLOX的环…...

基于小程序的汽车俱乐部系统的设计与实现(论文+源码)_kaic

目录 前 言 1 系统概述 1.1 系统主要功能 1.2 开发及运行环境 2 系统分析和总体设计 2.1 需求分析 2.2 可行性分析 2.3 设计目标 2.4 项目规划 2.5 系统开发语言简介 2.6 系统功能模块图 3 系统数据库设计 3.1 数据库开发工具简介 3.2 数据库需求分析 3.3 数据库…...

ProgrammingArduino物联网

programming_arduino_ed2 IO 延时闪灯 void setup() {pinMode(13, OUTPUT); }void loop() {digitalWrite(13, HIGH);delay(500);digitalWrite(13, LOW);delay(500); }// sketch 03-02 加入变量 int ledPin 13; int delayPeriod 500;void setup() {pinMode(ledPin, OUTPUT)…...

SSM框架的学习与应用(Spring + Spring MVC + MyBatis)-Java EE企业级应用开发学习记录(第一天)Mybatis的学习

SSM框架的学习与应用(Spring Spring MVC MyBatis)-Java EE企业级应用开发学习记录&#xff08;第一天&#xff09;Mybatis的学习 一、当前的主流框架介绍(这就是后期我会发出来的框架学习) Spring框架 ​ Spring是一个开源框架&#xff0c;是为了解决企业应用程序开发复杂…...

Programming abstractions in C阅读笔记: p118-p122

《Programming Abstractions In C》学习第49天&#xff0c;p118-p122&#xff0c;总结如下&#xff1a; 一、技术总结 1.随机数 (1)seed p119&#xff0c;“The initial value–the value that is used to get the entire process start–is call a seed for the random ge…...

2023国赛数学建模思路 - 案例:ID3-决策树分类算法

文章目录 0 赛题思路1 算法介绍2 FP树表示法3 构建FP树4 实现代码 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 算法介绍 FP-Tree算法全称是FrequentPattern Tree算法&#xff0c;就是频繁模…...

selenium 选定ul-li下拉选项中某个指定选项

场景&#xff1a;selenium的下拉选项是ul-li模式&#xff0c;选定某个指定的选项。 from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # 显示等待def select_li(self, text, *ul_locator):"…...

回归预测 | MATLAB实现FA-SVM萤火虫算法优化支持向量机多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现FA-SVM萤火虫算法优化支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现FA-SVM萤火虫算法优化支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09;效果一览基本介绍…...

使用pytorch 的Transformer进行中英文翻译训练

下面是一个使用torch.nn.Transformer进行序列到序列&#xff08;Sequence-to-Sequence&#xff09;的机器翻译任务的示例代码&#xff0c;包括数据加载、模型搭建和训练过程。 import torch import torch.nn as nn from torch.nn import Transformer from torch.utils.data im…...

解决element的select组件创建新的选项可多选且opitions数据源中有数据的情况下,回车不能自动选中创建的问题

前言 最近开发项目使用element-plus库内的select组件&#xff0c;其中有提供一个创建新的选项的用法&#xff0c;但是发现一些小问题&#xff0c;在此记录 版本 “element-plus”: “^2.3.9”, “vue”: “^3.3.4”, 问题 1、在options数据源中无数据的时候&#xff0c;在输入框…...

人工智能大模型加速数据库存储模型发展 行列混合存储下的破局

数据存储模型 ​专栏内容&#xff1a; postgresql内核源码分析手写数据库toadb并发编程toadb开源库 个人主页&#xff1a;我的主页 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物. 概述 在数据库的发展过程中&#xff0c;关…...

K8S用户管理体系介绍

1 K8S账户体系介绍 在k8s中&#xff0c;有两类用户&#xff0c;service account和user&#xff0c;我们可以通过创建role或clusterrole&#xff0c;再将账户和role或clusterrole进行绑定来给账号赋予权限&#xff0c;实现权限控制&#xff0c;两类账户的作用如下。 server acc…...

实现chatGPT 聊天样式

效果图 代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Chat Example</title&g…...

day9 STM32 I2C总线通信

I2C总线简介 I2C总线介绍 I2C&#xff08;Inter-Integrated Circuit&#xff09;总线&#xff08;也称IIC或I2C&#xff09;是由PHILIPS公司开发的两线式串行总线&#xff0c;用于连接微控制器及其外围设备&#xff0c;是微电子通信控制领域广泛采用的一种总线标准。 它是同步通…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件&#xff0c;然后打开终端&#xff0c;进入下载文件夹&#xff0c;键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

docker 部署发现spring.profiles.active 问题

报错&#xff1a; org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...

基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解

JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用&#xff0c;结合SQLite数据库实现联系人管理功能&#xff0c;并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能&#xff0c;同时可以最小化到系统…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

C语言中提供的第三方库之哈希表实现

一. 简介 前面一篇文章简单学习了C语言中第三方库&#xff08;uthash库&#xff09;提供对哈希表的操作&#xff0c;文章如下&#xff1a; C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...

LOOI机器人的技术实现解析:从手势识别到边缘检测

LOOI机器人作为一款创新的AI硬件产品&#xff0c;通过将智能手机转变为具有情感交互能力的桌面机器人&#xff0c;展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家&#xff0c;我将全面解析LOOI的技术实现架构&#xff0c;特别是其手势识别、物体识别和环境…...