<C++> 二叉搜索树

目录

二叉搜索树

1. 概念

2. 二叉搜索树操作

2.1 基础结构

2.2 非递归版

1. 查找

2. 插入

3. 删除

2.3 递归版

1. 查找

2. 插入

3. 删除

2.4 拷贝构造函数

2.5 赋值运算符重载

2.6 析构函数

2.7 完整代码

3. 二叉搜索树的应用

4. 二叉搜索树的性能


二叉搜索树

1. 概念

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

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

由于二叉搜索树的性质,该树的中序遍历就是递增序列

 

2. 二叉搜索树操作

2.1 基础结构

	template<class K>struct BSTreeNode{BSTreeNode<K>* _left;BSTreeNode<K>* _right;K _key;BSTreeNode(const K& key):_key(key), _left(nullptr), _right(nullptr){}};template<class K>class BSTree{typedef BSTreeNode<K> Node;public:BSTree():_root(nullptr){}private:Node* _root;};

2.2 非递归版

1. 查找

  • key小于cur->_key,则往左子树找
  • key大于cur->_key,则往右子树找
		bool Find(const K& key){Node* cur = _root;while (cur){if (cur->_key > key){cur = cur->_left;}else if (cur->_key < key){cur = cur->_right;}else{return true;}}return false;}
2. 插入

  • 插入要先找到合适的空位
  • 如果已经之前已经存在,那么return false
  • 找到空位之后,new出一个新节点,在链接时我们要获取parent节点,这就需要我们提前记录parent节点
  • 链接时还要判断 key 与 parent->_key大小关系,因为我们找到了合适的位置,但是没有记录是在左还是在右
bool Insert(const K& key){//如果树为空,直接new一个根节点if (_root == nullptr){_root = new Node(key);return true;}//记录父节点,最后链到父节点Node* parent = nullptr;Node* cur = _root;//找到合适的空位置while (cur){if (cur->_key < key){parent = cur;cur = cur->_right;}else if (cur->_key > key){parent = cur;cur = cur->_left;}else{return false;}}//由于不知道插入的节点与父亲的key大小关系,所以再判断一下是插到左边还是右边cur = new Node(key);if (parent->_key < key){parent->_right = cur;}else{parent->_left = cur;}return true;}
3. 删除

 

  • 先查找该节点是否存在,如果存在,再看以下几点
  • 删除节点情况分三种:该节点左孩子为空、该节点右孩子为空、该节点左右孩子都有
  • 左孩子为空:将右节点链接到parent上即可,此时还要判断cur在parent的哪一边,如果cur在parent的右边,那么cur的所有孩子必然比parent的key大,所以将cur的right链接到parent的right即可
  • 右孩子为空:同理
  • 左右孩子都存在:此时我们可以找该节点左子树的最右节点,或右子树的最左节点,这两个节点都是最接近根节点key值的节点(因为二叉搜索树的性质,当节点无穷时,这两个节点的key值将从左和从右边无限趋近于根节点的key值),找到节点后与根节点交换key值,此时如果是左子树的最右节点,那么该节点是绝不可能存在右子树,所以此时将该节点的左子树链接到parent节点即可(提前记录parent,在判断cur在parent的哪一边)
  • 最后不要忘了delete被删除的节点
bool Erase(const K& key){Node* parent = nullptr;Node* cur = _root;//先看看能不能找到这个节点while (cur){if (cur->_key < key){parent = cur;cur = cur->_right;}else if (cur->_key > key){parent = cur;cur = cur->_left;}else  //找到节点了{//该节点左为空if (cur->_left == nullptr){if (cur == _root){_root = cur->_right;}else  //再看看cur在父节点parent的哪一边,在哪一边就把孤儿链接到哪一边{if (parent->_right == cur){parent->_right = cur->_right;}else{parent->_left = cur->_right;}}}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;}}}else  //该节点左右都不为空{Node* parent = cur;Node* leftMax = cur->_left;while (leftMax->_right){parent = leftMax;leftMax = leftMax->_right;}swap(leftMax->_key, cur->_key);if (parent->_left == leftMax){parent->_left = leftMax->_left;}else{parent->_right = leftMax->_left;}cur = leftMax;}delete cur;return true;}}return false;}

2.3 递归版

        由于用户不传递root参数,所以FindR内层封装一个获取root参数的函数,其他函数同理

1. 查找

  • 如果找不到返回false,找到了返回true。比key小,往右子树递归找;比key大,往左子树递归找。
		bool FindR(const K& key){return _FindR(_root, key);}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;}}
2. 插入

  • insert函数神之一手的地方就是参数类型 Node*&,当它递归下去时 root 其实是它的父节点的 left 或 right 的引用!它可以不用提前保存parent的信息,直接链接新节点!
		bool InsertR(const K& key){return _InsertR(_root, key);}//Node*& root,这里的引用是神之一手,因为在连接的时候可以不用再去记录parent//在链接的时候,那个root是引用的父亲的root->_right或root->_left !!bool _InsertR(Node*& root, const K& key){if (root == nullptr){//这个root是引用的父亲的root->_right或root->_left,这一步是直接链接了!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{//已经有该节点了,返回falsereturn false;}}
3. 删除

  • 先找到要删除的节点,然后再提前保存该节点,为了后续的delete
  • 同样的,erase的参数也是Node*&,它极大方便了节点的链接
  • 找到节点后,如果该节点的左节点为空,那么直接root = root->_right;如果右节点为空,那么 root = root->_left,这就是Node* &的强大之处。那么可能有疑问,非递归版本为什么不能用引用?循环版本不能使用引用,是因为引用不能改变指向!递归可以使用引用是因为每次都是一个新的栈帧
  • 如果左右节点都存在,找左子树最右节点,交换key值,再erase掉key的节点(注意,不能从root开始找,因为root此时已经被交换key值了,递归会往右边去找,这就会导致找错了
  • 最后Erase()这里不能传leftMax->_left,因为leftMax是局部变量,最后子节点会链接不上真正的root

		bool EraseR(const K& key){return _EraseR(_root, key);}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(leftMax->_key, root->_key);//这里不能传leftMax->_left,因为是别名,leftMax是局部变量,最后子节点会链接不上真正的rootreturn _EraseR(root->_left, key);}delete del;return true;}}

2.4 拷贝构造函数

  • 根据前序序列递归拷贝
  • 该递归就是从最左边开始链接,再从最底层往上

		BSTree(const BSTree<K>& t){_root = Copy(t._root);}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;}

2.5 赋值运算符重载

  • 现代写法
		BSTree<K>& operator=(BSTree<K> t){swap(_root, t._root);return *this;}

2.6 析构函数

  • 递归式析构
		~BSTree(){Destory(_root);}void Destory(Node*& root){if (root == nullptr)return;Destory(root->_left);Destory(root->_right);delete root;root = nullptr;}

2.7 完整代码

namespace key
{template<class K>struct BSTreeNode{BSTreeNode<K>* _left;BSTreeNode<K>* _right;K _key;BSTreeNode(const K& key):_key(key), _left(nullptr), _right(nullptr){}};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(){Destory(_root);}bool Insert(const K& key){//如果树为空,直接new一个根节点if (_root == nullptr){_root = new Node(key);return true;}//记录父节点,最后链到父节点Node* parent = nullptr;Node* cur = _root;//找到合适的空位置while (cur){if (cur->_key < key){parent = cur;cur = cur->_right;}else if (cur->_key > key){parent = cur;cur = cur->_left;}else{return false;}}//由于不知道插入的节点与父亲的key大小关系,所以再判断一下是插到左边还是右边cur = new Node(key);if (parent->_key < key){parent->_right = cur;}else{parent->_left = cur;}return true;}bool Find(const K& key){Node* cur = _root;while (cur){if (cur->_key > key){cur = cur->_left;}else if (cur->_key < key){cur = cur->_right;}else{return true;}}return false;}bool Erase(const K& key){Node* parent = nullptr;Node* cur = _root;//先看看能不能找到这个节点while (cur){if (cur->_key < key){parent = cur;cur = cur->_right;}else if (cur->_key > key){parent = cur;cur = cur->_left;}else  //找到节点了{//该节点左为空if (cur->_left == nullptr){if (cur == _root){_root = cur->_right;}else  //再看看cur在父节点parent的哪一边,在哪一边就把孤儿链接到哪一边{if (parent->_right == cur){parent->_right = cur->_right;}else{parent->_left = cur->_right;}}}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;}}}else  //该节点左右都不为空{Node* parent = cur;Node* leftMax = cur->_left;while (leftMax->_right){parent = leftMax;leftMax = leftMax->_right;}swap(leftMax->_key, cur->_key);if (parent->_left == leftMax){parent->_left = leftMax->_left;}else{parent->_right = leftMax->_left;}cur = leftMax;}delete cur;return true;}}return false;}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: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 Destory(Node*& root){if (root == nullptr)return;Destory(root->_left);Destory(root->_right);delete root;root = nullptr;}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(leftMax->_key, root->_key);//这里不能传leftMax->_left,因为是别名,leftMax是局部变量,最后子节点会链接不上真正的rootreturn _EraseR(root->_left, key);}delete del;return true;}}//Node*& root,这里的引用是神之一手,因为在连接的时候可以不用再去记录parent//在链接的时候,那个root是引用的父亲的root->_right或root->_left !!bool _InsertR(Node*& root, const K& key){if (root == nullptr){//这个root是引用的父亲的root->_right或root->_left,这一步是直接链接了!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{//已经有该节点了,返回falsereturn 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 == NULL){return;}_InOrder(root->_left);cout << root->_key << " ";_InOrder(root->_right);}private:Node* _root;};void TestBSTree1(){int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };BSTree<int> t;for (auto e : a){t.Insert(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.Erase(e);}t.InOrder();}}

3. 二叉搜索树的应用

1. K模型:K模型即只有key作为关键码,结构中只需要存储Key即可,关键码即为需要搜索到的值

比如:给一个单词word,判断该单词是否拼写正确,具体方式如下:

  • 以单词集合中的每个单词作为key,构建一棵二叉搜索树
  • 在二叉搜索树中检索该单词是否存在,存在则拼写正确,不存在则拼写错误。

2. KV模型:每一个关键码key,都有与之对应的值Value,即<Key, Value>的键值对。该种方式在现实生活中非常常见:比如英汉词典就是英文与中文的对应关系,通过英文可以快速找到与其对应的中文,英文单词与其对应的中文<word, chinese>就构成一种键值对;再比如统计单词次数,统计成功后,给定单词就可快速找到其出现的次数,单词与其出现次数就是<word, count>就构成一种键值对

比如:实现一个简单的英汉词典dict,可以通过英文找到与其对应的中文,具体实现方式如下:

  • <单词,中文含义>为键值对构造二叉搜索树,注意:二叉搜索树需要比较,键值对比较时只比较
  • 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;// 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, 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;};void TestBSTree1(){//BSTree<string, Date> carTree;BSTree<string, string> dict;dict.InsertR("insert", "插入");dict.InsertR("sort", "排序");dict.InsertR("right", "右边");dict.InsertR("date", "日期");string str;while (cin >> str){BSTreeNode<string, string>* ret = dict.FindR(str);if (ret){cout << ret->_value << endl;}else{cout << "无此单词" << endl;}}}void TestBSTree2(){// 统计水果出现的次数string arr[] = { "西瓜", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };BSTree<string, int> countTree;for (auto& str : arr){auto ret = countTree.FindR(str);if (ret == nullptr){countTree.InsertR(str, 1);}else{ret->_value++;}}countTree.InOrder();}
}

相比只有key版本,key_value只是在结构体内多加了value而已,部分函数原理也没有变

4. 二叉搜索树的性能

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

        对有n个结点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二叉搜索树的深度的函数,即结点越深,则比较次数越多。

        但对于同一个关键码集合,如果各关键码插入的次序不同,可能得到不同结构的二叉搜索树:

 

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

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

相关文章

SpringBoot+Vue3整合minio,实现分布式文件存储

文章目录 几种常用的文件存储安装和使用minioSpringBoot整合minio 基本所有的软件项目都会需要文件存储功能&#xff0c;图片、视频存储。 几种常用的文件存储 经常用的几种方案&#xff0c;直接存在本地文件夹&#xff0c;开发一个简单的系统当然没有问题。随机系统所需的资源…

微服务多个模块启动,端口被占用,yml配置文件读不到

刚刚提交到gitee自己的仓库&#xff0c;拉下来还是报错&#xff0c;然后看到一个解决方法&#xff1a; <build><resources><resource><directory>src/main/java</directory><includes><include>**/*.yml</include><includ…

推荐一个java低代码开发平台-橙单

文章目录 前言一、项目介绍二、技术选型三、项目特点四、基础功能介绍五、源码下载六、官方文档总结 前言 大家好&#xff0c;今天为大家推荐一个开箱即用&#xff0c;快速开发的低代码平台。项目采用 Boot3 Flowable7 Sa-Token Vue3技术栈。 一、项目介绍 橙单中台化低代…

Datawhale AI 夏令营(第五期) 李宏毅苹果书 Task 1 《深度学习详解(入门)》- 1.1 通过案例了解机器学习

预测本频道观看人数&#xff08;上&#xff09; - 机器学习基本概念简介_哔哩哔哩_bilibili 1 隐藏任务&#xff1a;找出本篇中形如回归&#xff08;regression&#xff09;加粗字体的术语&#xff0c;并用自己的话进行解释&#xff0c;列成表格 术语解释机器学习&#xff08;…

服务器数据恢复—重建RAID失败导致数据丢失的数据恢复案例

服务器数据恢复环境&#xff1a; 某品牌服务器中有一组由4块SAS磁盘做的RAID5磁盘阵列。该服务器操作系统为windows server&#xff0c;运行了一个单节点Oracle&#xff0c;数据存储为文件系统&#xff0c;无归档。该oracle数据库的数据量不大&#xff0c;oracle数据库内只有一…

WPF——动态排名图表实现

开发环境 VS2022 .NET 8.0 MVVM Toolkit 8.2.2 需求 开发中需要实现按照成绩动态指名&#xff0c;以展示当前的竞赛成绩的一个实时情况及变化。 即如下效果&#xff1a; 需求分析 按照接收到的信息&#xff0c;就是要将获取到的集合排序&#xff0c;并且要将排序前后的变…

【AI绘画】Midjourney前置指令/settings设置详解

文章目录 &#x1f4af;Midjourney前置指令/settings设置详解&#x1f4af;Use the default model&#xff08;AI绘画所使用的大模型&#xff09;Midjourney Model&#xff08;Midjourney 模型&#xff09;Niji Model&#xff08;Niji模型&#xff09; &#x1f4af;Midjourney…

外网爆火的LLM应用手册来了!内行人都在学的大模型黑书,豆瓣评分高达9.9!!!

Transformer模型介绍 Transformer 是工业化、同质化的后深度学习模型&#xff0c;其设计目标是能够在高性能计算机(超级计算机)上以并行方式进行计算。通过同质化&#xff0c;一个Transformer 模型可以执行各种任务&#xff0c;而不需要微调。Transformer 使用数十亿参数在数…

【Java数据结构】---二叉树OJ

乐观学习&#xff0c;乐观生活&#xff0c;才能不断前进啊&#xff01;&#xff01;&#xff01; 我的主页&#xff1a;optimistic_chen 我的专栏&#xff1a;c语言 &#xff0c;Java 欢迎大家访问~ 创作不易&#xff0c;大佬们点赞鼓励下吧~ 文章目录 相同的树另一颗树的子树翻…

ES 模糊查询 wildcard 的替代方案探索

一、Wildcard 概述 Wildcard 是一种支持通配符的模糊检索方式。在 Elasticsearch 中&#xff0c;它使用星号 * 代表零个或多个字符&#xff0c;问号 ? 代表单个字符。 其使用方式多样&#xff0c;例如可以通过 {"wildcard": {"field_name": "value&…

docker-compose示例:nacos单机部署

前面咱们完成了docker基本环境搭建&#xff0c;下面就趁热打铁来练习下nacos的单机部署。 参考官方文档&#xff1a;Nacos Docker 快速开始。考虑到官方搭建教程过于精炼&#xff0c;笔者把搭建过程分享给大家。 文章目录 下载最新部署源码解决网络导致的sql文件下不下来docke…

unity AssetBundle 使用_什么是AssetBundle_导入必要的插件_创建AssetBundles_AB包资源下载_大文件下载

一、什么是AssetBundle&#xff1f; 定义AssetBundle。 AssetBundle 是一个存档文件&#xff0c;包含可在运行时由 Unity 加载的特定于平台的非代码资源&#xff08;比如模型、纹理、预制件、音频剪辑甚至整个场景&#xff09;。AssetBundle 可以表示彼此之间的依赖关系&…

防范小程序隐私合规风险,筑牢用户信任防线

随着国内APP软件生态的成熟&#xff0c;依托于头部APP的小程序逐渐成为零售、娱乐、出行等行业必选的获客渠道之一。较低的开发成本和成熟的用户营销功能&#xff0c;令小程序的数量在过去几年呈指数级增长。截止2023年&#xff0c;头部APP内集成的小程序总量已超千万。然而&am…

OpenCV(开源计算机视觉库)

OpenCV&#xff08;开源计算机视觉库&#xff09;是一个专注于实时计算机视觉的全面库&#xff0c;包含了丰富的工具和功能。以下是 OpenCV 中一些关键知识点的详细列表&#xff1a; 核心功能 基本结构&#xff1a;Mat、Scalar、Point、Size、Rect 等。 图像 I/O&#xff1a;读…

Latex 插入图片或表格导致页面空白过多

如图所示&#xff1a; Latex 插入图片或表格导致页面空白过多 我们可以采用这个方式来减少空白。 \documentclass{article} \usepackage{graphicx} % 包含图形支持 \usepackage{caption} % 提供更多对caption的控制% 设置标题上方和下方的间距 \setlength{\abovecaptionskip}{…

数据结构【链试结构二叉树】

&#x1f31f;个人主页&#xff1a;落叶 目录 ​编辑 实现链式结构⼆叉树 前中后序遍历&#xff1a; 遍历规则 代码实现 前序遍历&#xff1a; 中序遍历&#xff1a; 后序遍历&#xff1a; 图解遍历&#xff1a; 函数递归栈帧图&#xff1a; 结点个数以及高度等 【⼆…

Oracle归档日志满了,导致程序打不开,如何解决。

加油&#xff0c;新时代打工人&#xff01; 归档日志错误&#xff0c;登录不上&#xff0c;只能用system 角色登录&#xff0c; 错误提示 oracle 错误257 archiver error connect internal only until freed 解决cmd进入rman RMAN&#xff08;Recovery Manager&#xff09;是一…

数学基础(六)

一、分布 正态分布 二项式分布 均匀分布 卡方分布 二、核函数 核函数的目的&#xff1a; 将低维数据转换为高维数据 线性核函数&#xff1a; Linear核函数对数据不做任何变换 当特征已经比较丰富了&#xff0c;样本数据量巨大&#xff0c;需要进行实时得出结果时进行使用…

小程序学习day11-生命周期函数、组件所在页面的生命周期、自定义组件的插槽、自定义组件的父子通信

40、自定义组件&#xff08;续&#xff09;&#xff08;续&#xff09; &#xff08;10&#xff09;生命周期函数 1&#xff09;小程序里的全部生命周期函数 ①created&#xff08;在组件刚被创建时执行&#xff09;&#xff08;被创建&#xff0c;但未被放入页面&#xff09…

Servlet---axios框架 ▎路由守卫

前言 在现代Web应用中&#xff0c;前端和后端通常分离&#xff0c;前端使用框架&#xff08;如Vue.js、React&#xff09;与后端服务交互。Servlet是Java EE中处理HTTP请求的重要组成部分&#xff0c;能够生成动态Web内容。 Axios是一个基于Promise的HTTP客户端&#xff0c;简…