【C++数据结构】二叉树搜索树【完整版】

目录

一、二叉搜索树的定义

 二、二叉搜索树的实现:

1、树节点的创建--BSTreeNode

 2、二叉搜索树的基本框架--BSTree

3、插入节点--Insert

 4、中序遍历--InOrder

5、 查找--Find

6、 删除--erase

完整代码:

三、二叉搜索树的应用

1、key的模型 :判断在不在

2、key/value的模型:通过key找value 

key/value的应用场景

应用场景1--中英文互译

应用场景2--统计水果出现次数

 四、二叉搜索树性能分析


一、二叉搜索树的定义

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

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

 二、二叉搜索树的实现:

这里最好不用递归,递归比非递归更复杂,故用非递归实现

分两个文件:

BSTree.hpp(因为要用模板实现,而模板的实现和声明要放在一起的,若用模板实现就可用.hpp为后缀和 Test.c

1、树节点的创建--BSTreeNode

 是由节点组成的,故应写个BSTreeNode用来表示每个树节点,_left表示左指针,_right表示右指针,还有一个位置用来存值_key,因为无法确定存的是什么类型的值,故用模板来实现通用,设置成struct是因为树的节点对外是公开的,外部都可以访问的

template<class K>
struct BSTreeNode
{BSTreeNode(const K& key):_key(key), _left(nullptr), _right(nullptr){}BSTreeNode<K>* _left;BSTreeNode<K>* _right;K _key;
};

 2、二叉搜索树的基本框架--BSTree

对于树的成员变量,一个根节点即可

template<class K>
class BSTree //Binary Search Tree
{typedef BSTreeNode<K> Node;
public:private:Node* _root = nullptr;可以直接定义,就一个成员变量,无需写个构造函数
};

3、插入节点--Insert

 这个函数需要有返回值的,以bool作为返回类型,因为这棵树中不允许数据冗余,即不能出现相同的数据。

插入就是用性质:左子树的值都比当前根节点的值小,右子树的值都比当前根节点的值大

若插入一个数据key,从根节点(用cur指针来表示当前位置)开始往下比就好了

①、如果key比当前节点的值大,那就接着往右走

②、如果key比当前节点的值小,那就接着往左走

对于①②直到找到一个空位置插入即可

③、如果走的过程中遇到相等的值,说明该key值不能插入,但要注意一个条件,如果这棵树本来就为空,那就直接把数据插入到根节点中就好

链接问题:

插入一个节点,必然要与树链接,若不链接,这个节点就是个临时数据,出了作用域就没了,但若把他链接到树上就能正常访问了,故这里采用双指针法cur表示当前节点,再定义一个parent,每次cur走之前,先把cur赋值给parent,这样最后cur走到空了,parent能记录到cur的上一位置,而这上一位置就是要找的cur要与其链接的位置,至于cur插入到parent的左还是右,若值比parent的值大,则插到右边,小,则插到左边

bool Insert(const K& key)
{if (_root == nullptr){//若为空树,就给它一个节点_root = new Node(key);//new是开空间+初始化,所以要调用构造函数,你要写的return true;}Node* cur = _root;//从根节点开始比较Node* parent = nullptr;while (cur){//都会找一个空位置插入,不会说挪动节点来进行插入if (cur->_key > key){parent = cur;cur = cur->_left;}else if (cur->_key < key){parent = cur;cur = cur->_right;}else{//若在走的过程中遇到相同的数据,返回假,这个数据无法插入return false;}}cur = new Node(key);//向这个空位置插入数据//利用parent的位置与cur连接if (parent->_key > key)parent->_left = cur;//比根节点小,链接到左边elseparent->_right = cur;//比根节点大,链接到右边return true;
}

 4、中序遍历--InOrder

  这里用两个成员函数实现,为什么?中序遍历你要传树的根节点,而根节点就是类的私有成员变量,而你的中序遍历一定是在类外使用的,无法直接访问_root

解决方法:

法一、写个成员函数获得一下_root是可以的

法二、两个成员函数,即用InOrder来传这个_root,成员函数访问你_root一定是没问题的,那么_InOrder直接用来中序遍历即可,调用直接调用InOrder即可

void InOrder()
{_InOrder(_root);cout << endl;
}
//下面的可以放到private里面
void _InOrder(Node* root)
{if (root == nullptr)return;_InOrder(root->_left);cout << root->_key << " ";_InOrder(root->_right);
}

下面利用写的插入中序遍历测试代码


void testTree()
{BSTree<int> t;int a[] = { 5,3,4,1,7,8,2,6,0,9 };for (auto e : a){//数组是可以用迭代器来遍历的t.Insert(e);//插入节点到树中}t.InOrder();//中序遍历
}

 


5、 查找--Find

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;//走到空还没找到,说明没有此数据
}

6、 删除--erase

1、观察现象:  

删除2,让父亲指向我的右,删除8,让父亲指向我的右,5不好删,因为他有两个孩子

左为空,父亲指向我的右,右为空,父亲指向我的左,叶子节点可以归纳为左为空(右为空也行,这里就假设用左为空),因为叶子的左右都为空,它父亲的指向他的左还是右均可

左为空,

2、细节考虑

A、待删除节点左为空或右为空的情况(叶子结点可归类为左为空)

删除一个节点是让其父亲(Parent)的左指针还是右指针指向cur?

若cur的左子树为空】看cur到底是父亲的左子树还是右子树,若是父亲的左子树,则让父亲的左指向cur右子树 ,若为右子树,则让父亲的右指向cur的右子树

若cur的右子树为空】若是父亲的左子树,则让父亲的左指向cur左子树 ,若为右子树,则让父亲的右指向cur的左子树

B、待删除节点左右都不为空的情况

节点的左右子树都不为空,不能直接删除,直接删除会导致二叉搜索树混乱,故用替代法删除。

因为要符合左子树都比根节点小,右子树都比根节点大的性质,故要找左子树的最大节点或右子树的最小节点去替代它。(左子树最右边的节点是左子树最大节点,右子树的最左边的节点是右子树最小节点)【故假设我们下面就用右子树的最小节点】

比如删除7,可以用8(7的右子树的最左节点)来替代,那么替换完后,我删除这个7就可以直接删了,那么这个问题又转换到了被删除节点的左为空或者右为空,因为替换节点一定要么是最左边的节点要么是最右边的节点(不一定是叶子结点),那这个替换节点的左右子树一定存在左子树右子树有个为空的情况

所以删除 分三种情况

问题1:

删除一定要找到父亲,因为删完了还存在链接关系,所以单单用find去找是不行的,他找不到他的父亲节点,故还是用双指针法

 因为链接问题,所以删除关键看cur是在父亲的左还是右,而不是看cur的左边为空还是右边为空,这不符合所有场景

问题2:

最左节点不一定就是叶子结点,比如这里删除7,它的右子树的最左节点是8,则8替换完7后,8要被删除,他被删除完后,parent的右指针要指向rightMin的右节点

问题3:

parent初始值不能为nullptr,若删除7【che指针指向7】,因为要删除cur,Rightmin刚上来就=8,Rightmin的左子树为空,while循环都没进去,而parent它还是nullptr,那后续的链接肯定会有问题的,所以parent应该一上来就赋值为cur,而不是nullptr

问题4:

若要删除的节点是根节点,也要特别考虑,左为空,则让根=它的右节点,右为空,则让根=它的左节点

bool Erase(const K& key)
{Node* cur = _root;Node* parent = nullptr;while (cur){if (cur->_key > key){parent = cur;cur = cur->_left;}else if (cur->_key < key){parent = cur;cur = cur->_right;}else{//找到了,开始删除//1.左为空if (cur->_left == nullptr){if (cur == _root)_root = cur->_right;else{if (parent->_left == cur)parent->_left = cur->_right;//cur在父亲的左边,就让父亲的左指向cur的左elseparent->_right = cur->_right;//cur在父亲的右边,就让父亲的右指向cur的右}delete cur;}//2.右为空else if (cur->_right == nullptr){if (cur == _root)_root = cur->_left;else{if (parent->_right == cur)parent->_right = cur->_left;//cur在父亲的右边,就让父亲的右指向cur的左elseparent->_left = cur->_left;//cur在父亲的左边,就让父亲的左指向cur的右}delete cur;}//3.左右都不为空else{//找左子树的最右节点或右子树的最小节点去替代//这里用右子树的最小节点来替代Node* parent = cur;Node* Rightmin = cur->_right;//若用右树的最小节点,即右树最左节点while (Rightmin->_left){//最左节点的左子树一定为空,故为判断条件parent = Rightmin;//替换节点不一定是叶子结点,故还要用parent来链接Rightmin = Rightmin->_left;}cur->_key = Rightmin->_key;//用cur的值来替代//转换成删除Rightmin//若它是parent的右子树,则父亲的右指向它的右//若它是parent的左子树,则父亲的左指向它的左if (Rightmin == parent->_left)parent->_left = Rightmin->_right;elseparent->_right = Rightmin->_right;delete Rightmin;}return true;}}return false;//cur都为空了还没找到,则该数据不存在
}

完整代码:

BSTree.hpp

#pragma once
#include<iostream>
using namespace std;template<class K>
struct BSTreeNode
{BSTreeNode(const K& key):_key(key), _left(nullptr), _right(nullptr){}BSTreeNode<K>* _left;BSTreeNode<K>* _right;K _key;};
template<class K>
class BSTree //Binary Search Tree
{typedef BSTreeNode<K> Node;
public:bool Insert(const K& key){if (_root == nullptr){//若为空树,就给它一个节点_root = new Node(key);//new是开空间+初始化,所以要调用构造函数,你要写的return true;}Node* cur = _root;//从根节点开始比较Node* parent = nullptr;while (cur){//都会找一个空位置插入,不会说挪动节点来进行插入if (cur->_key > key){parent = cur;cur = cur->_left;}else if (cur->_key < key){parent = cur;cur = cur->_right;}else{//若在走的过程中遇到相同的数据,返回假,这个数据无法插入return false;}}cur = new Node(key);//向这个空位置插入数据//利用parent的位置与cur连接if (parent->_key > key)parent->_left = cur;//比根节点小,链接到左边elseparent->_right = 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* cur = _root;Node* parent = nullptr;while (cur){if (cur->_key > key){parent = cur;cur = cur->_left;}else if (cur->_key < key){parent = cur;cur = cur->_right;}else{//找到了,开始删除//1.左为空if (cur->_left == nullptr){if (cur == _root)_root = cur->_right;else{if (parent->_left == cur)parent->_left = cur->_right;//cur在父亲的左边,就让父亲的左指向cur的左elseparent->_right = cur->_right;//cur在父亲的右边,就让父亲的右指向cur的右}delete cur;}//2.右为空else if (cur->_right == nullptr){if (cur == _root)_root = cur->_left;else{if (parent->_right == cur)parent->_right = cur->_left;//cur在父亲的右边,就让父亲的右指向cur的左elseparent->_left = cur->_left;//cur在父亲的左边,就让父亲的左指向cur的右}delete cur;}//3.左右都不为空else{//找左子树的最右节点或右子树的最小节点去替代//这里用右子树的最小节点来替代Node* parent = cur;Node* Rightmin = cur->_right;//若用右树的最小节点,即右树最左节点while (Rightmin->_left){//最左节点的左子树一定为空,故为判断条件parent = Rightmin;//替换节点不一定是叶子结点,故还要用parent来链接Rightmin = Rightmin->_left;}cur->_key = Rightmin->_key;//用cur的值来替代//转换成删除Rightmin//若它是parent的右子树,则父亲的右指向它的右//若它是parent的左子树,则父亲的左指向它的左if (Rightmin == parent->_left)parent->_left = Rightmin->_right;elseparent->_right = Rightmin->_right;delete Rightmin;}return true;}}return false;//cur都为空了还没找到,则该数据不存在}void InOrder(){_InOrder(_root);cout << endl;}//下面的可以放到private里面void _InOrder(Node* root){if (root == nullptr)return;_InOrder(root->_left);cout << root->_key << " ";_InOrder(root->_right);}private:Node* _root = nullptr;//可以直接定义,就一个成员变量,无需写个构造函数
};void testTree()
{BSTree<int> t;int a[] = { 5,3,4,1,7,8,2,6,0,9 };for (auto e : a){//数组是可以用迭代器来遍历的t.Insert(e);//插入节点到树中}t.InOrder();//中序遍历
}

 Test.cpp

#include"BSTree.hpp"int main()
{testTree();return 0;
}

三、二叉搜索树的应用

搜索树使用场景:

1、key的模型 :判断在不在

 比如进入校园要刷校园卡,卡本质里面有芯片,芯片上存储信息,把学校所有学员的信息存到二叉搜索树(因为他的查找效率很高),然后用机器扫描卡,看你卡的信息是否在我的树中,在就让你进

2、key/value的模型:通过key找value 

①、高铁刷身份证

买了票就能进站,刷身份证读的是身份证号码,【key就是身份证,value就是票的信息】然后通过身份证到后台服务器查是否有票的信息,是否是这个车站,这个车次等等,即通过身份证找value

②、中英文互译

中文就是key,英文就是value,即通过中文找英文或通过英文找中文。

③、统计次数

统计次数,即通过一个值找另一个值,用搜索树实现的原因是二叉搜索树的效率高,搜索快

key/value模型的实现只需在我们实现的二叉搜索树中改动一下代码即可,即节点里面除了有key,还有value,但是比较大小的过程还是用key来比较,和value没关系,找到了key就相当于找到了value,因为两者在同一节点中,还要修改的就是Find函数,返回值变成返回节点的指针而不是bool值,因为这样返回的节点既有key又有value

注意:

对于搜索树的修改,搜索树中key是不允许修改的

如果是kv模型的搜索树,可以修改value,但不能修改key,就是因为你改了key就不一定满足二叉搜索树的条件了

kv模型的完整代码:

BSTree.hpp :

//key/value模型
#include<iostream>
#include<string>
using namespace std;template<class K, class V>
struct BSTreeNode
{BSTreeNode(const K& key,const V& value):_key(key),_value(value), _left(nullptr), _right(nullptr){}BSTreeNode<K,V>* _left;BSTreeNode<K,V>* _right;K _key;V _value;};
template<class K, class V>
class BSTree //Binary Search Tree
{typedef BSTreeNode<K,V> Node;
public:bool Insert(const K& key, const V& value){if (_root == nullptr){//若为空树,就给它一个节点_root = new Node(key, value);//new是开空间+初始化,所以要调用构造函数,你要写的return true;}Node* cur = _root;//从根节点开始比较Node* parent = nullptr;while (cur){//都会找一个空位置插入,不会说挪动节点来进行插入if (cur->_key > key){parent = cur;cur = cur->_left;}else if (cur->_key < key){parent = cur;cur = cur->_right;}else{//若在走的过程中遇到相同的数据,返回假,这个数据无法插入return false;}}cur = new Node(key,value);//向这个空位置插入数据//利用parent的位置与cur连接if (parent->_key > key)parent->_left = cur;//比根节点小,链接到左边elseparent->_right = cur;//比根节点大,链接到右边return true;}Node* 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 cur;//说明相等,则找到了,返回真}}return nullptr;}bool Erase(const K& key){Node* cur = _root;Node* parent = nullptr;while (cur){if (cur->_key > key){parent = cur;cur = cur->_left;}else if (cur->_key < key){parent = cur;cur = cur->_right;}else{//找到了,开始删除//1.左为空if (cur->_left == nullptr){if (cur == _root)_root = cur->_right;else{if (parent->_left == cur)parent->_left = cur->_right;//cur在父亲的左边,就让父亲的左指向cur的左elseparent->_right = cur->_right;//cur在父亲的右边,就让父亲的右指向cur的右}delete cur;}//2.右为空else if (cur->_right == nullptr){if (cur == _root)_root = cur->_left;else{if (parent->_right == cur)parent->_right = cur->_left;//cur在父亲的右边,就让父亲的右指向cur的左elseparent->_left = cur->_left;//cur在父亲的左边,就让父亲的左指向cur的右}delete cur;}//3.左右都不为空else{//找左子树的最右节点或右子树的最小节点去替代//这里用右子树的最小节点来替代Node* parent = cur;Node* Rightmin = cur->_right;//若用右树的最小节点,即右树最左节点while (Rightmin->_left){//最左节点的左子树一定为空,故为判断条件parent = Rightmin;//替换节点不一定是叶子结点,故还要用parent来链接Rightmin = Rightmin->_left;}cur->_key = Rightmin->_key;//用cur的值来替代//转换成删除Rightmin//若它是parent的右子树,则父亲的右指向它的右//若它是parent的左子树,则父亲的左指向它的左if (Rightmin == parent->_left)parent->_left = Rightmin->_right;elseparent->_right = Rightmin->_right;delete Rightmin;}return true;}}return false;//cur都为空了还没找到,则该数据不存在}void InOrder(){_InOrder(_root);cout << endl;}//下面的可以放到private里面void _InOrder(Node* root){if (root == nullptr)return;_InOrder(root->_left);cout << root->_key << ":" <<root->_value << endl;_InOrder(root->_right);}private:Node* _root = nullptr;//可以直接定义,就一个成员变量,无需写个构造函数
};void testTree1()
{BSTree<string, string>dict;//字典dict.Insert("sort", "排序");dict.Insert("polynomial", "多项式");dict.Insert("femininity", "女性");string str;while (cin >> str){BSTreeNode<string, string>* ret = dict.Find(str);if (ret){cout << ret->_value << endl;}else{cout << "无此单词" << endl;}}
}void testTree2()
{string strArr[] = { "西瓜","西瓜","香蕉","樱桃","西瓜","西瓜","香蕉" };BSTree<string, int> countTree;//key是string,value是intfor (auto str : strArr){BSTreeNode<string, int>* ret = countTree.Find(str);if (ret == nullptr){//第一次出现,就插入这个水果,出现一次,因为一开始树为空countTree.Insert(str, 1);}else{//出现过了,就++次数ret->_value++;}}countTree.InOrder();
}

 Test.cpp

#include"BSTree.hpp"int main()
{//testTree1();testTree2();return 0;
}

key/value的应用场景

应用场景1--中英文互译

key/value模型测试下面代码逻辑(中英文互译

 

应用场景2--统计水果出现次数

有一堆水果,请你统计水果出现的次数

 四、二叉搜索树性能分析

 

如果插入的数据是有序的或者接近有序的,那么搜索树效率就完全没办法保障

如:1  2  3  4  5  6  7  8,对于树就变成了单支树,搜索树的效率最坏的情况下是O(N)

如何解决?平衡树1、AVLTree   2、红黑树

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

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

相关文章

工具学习--easyexcel-3.x 使用--写入基本使用,自定义转换--动态表头以及宽设置-

写在前面&#xff1a; easyexcel是alibaba开发简单导出未excel的工具。使用的情况还是比较多的。 文章目录 依赖导入写Excel快速入门对象设置ExcelProperty设置列属性ExcelIgnore 忽视列宽、行高格式转换时间格式化数字格式化自定义格式化 合并单元格其他更加个性化需求动态表…

【Java 进阶篇】MySQL多表关系详解

MySQL是一种常用的关系型数据库管理系统&#xff0c;它允许我们创建多个表格&#xff0c;并通过各种方式将这些表格联系在一起。在实际的数据库设计和应用中&#xff0c;多表关系是非常常见的&#xff0c;它能够更好地组织和管理数据&#xff0c;实现数据的复杂查询和分析。本文…

react+IntersectionObserver实现页面丝滑帧动画

实现效果&#xff1a; 加入帧动画前&#xff1a; 普通的静态页面 加入帧动画后&#xff1a; 可以看到&#xff0c;加入帧动画后&#xff0c;页面效果还是比较丝滑的。 技术实现 加入animation动画类 先用 **scss **定义三种动画类&#xff1a; .withAnimation {.fade1 {ani…

JavaScript Web APIs第二天笔记

Web APIs - 第2天 学会通过为DOM注册事件来实现可交互的网页特效。 能够判断函数运行的环境并确字 this 所指代的对象理解事件的作用&#xff0c;知道应用事件的 3 个步骤 学习会为 DOM 注册事件&#xff0c;实现简单可交互的网页特交。 事件 事件是编程语言中的术语&#xff…

Word | 简单可操作的快捷公式编号、右对齐和引用方法

1. 问题描述 在理工科论文的写作中&#xff0c;涉及到大量的公式输入&#xff0c;我们希望能够按照章节为公式进行编号&#xff0c;并且实现公式居中&#xff0c;编号右对齐的效果。网上有各种各样的方法来实现&#xff0c;操作繁琐和简单的混在一起&#xff0c;让没有接触过公…

Visual Studio 代码显示空格等空白符

1.VS2010: 快捷键&#xff1a;CtrlR,W 2.VS2017、VS2019、VS2022&#xff1a; 工具 -> 选项 -> 文本编辑器 -> 显示 -> 勾选查看空白

解决webpack报错:You forgot to add ‘mini-css-extract-plugin‘ plugin

现象&#xff1a; 原因&#xff1a; webpack5.72跟mini-css-extract-plugin有兼容性问题 解决办法&#xff1a;把 new MiniCssExtractPlugin()放在webpack配置文件中plugins数组的第一项&#xff1a; plugins: [ // 此处解决报错&#xff1a;You forgot to add mini-css-extra…

Java项目-文件搜索工具

目录 项目背景 项目效果 SQLite的下载安装 使用JDBC操作SQLite 第三方库pinyin4j pinyin4j的具体使用 封装pinyin4j 数据库的设计 创建实体类 实现DBUtil 封装FileDao 设计scan方法 多线程扫描 周期性扫描 控制台版本的客户端 图形化界面 设计图形化界面 项目…

最新AI创作系统源码ChatGPT源码+附详细搭建部署教程+AI绘画系统+支持国内AI提问模型

一、AI系统介绍 SparkAi创作系统是基于国外很火的ChatGPT进行开发的Ai智能问答系统。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧&am…

二十二,加上各种贴图

使用pbr的各种贴图&#xff0c;albedo,金属度&#xff0c;ao,法线&#xff0c;粗糙度&#xff0c;可以更好的控制各个片元 1&#xff0c;先加上纹理坐标 texCoords->push_back(osg::Vec2(xSegment, ySegment)); geom->setVertexAttribArray(3, texCoords, osg::Array::BI…

WebPack-打包工具

从图中我们可以看出&#xff0c;Webpack 可以将多种静态资源 js、css、less 转换成一个静态文件&#xff0c;减少了页面的请求. 下面举个例子 &#xff1a; main.js 我们只命名导出一个变量 export const name"老六"index.js import { name } from "./tset/…

聊聊并发编程——Condition

目录 一.synchronized wait/notify/notifyAll 线程通信 二.Lock Condition 实现线程通信 三.Condition实现通信分析 四.JUC工具类的示例 一.synchronized wait/notify/notifyAll 线程通信 关于线程间的通信&#xff0c;简单举例下&#xff1a; 1.创建ThreadA传入共享…

Vue之ElementUI实现登陆及注册

目录 ​编辑 前言 一、ElementUI简介 1. 什么是ElementUI 2. 使用ElementUI的优势 3. ElementUI的应用场景 二、登陆注册前端界面开发 1. 修改端口号 2. 下载ElementUI所需的js依赖 2.1 添加Element-UI模块 2.2 导入Element-UI模块 2.3 测试Element-UI是否能用 3.编…

【VUE复习·9】v-for 基础用法(循环渲染也叫列表渲染)

总览 1.v-for 都能循环什么 2.用法 一、v-for 都能遍历什么 能循环的东西包括&#xff1a;数组、对象、字符串&#xff08;和java里面的3个引用数据类型一样&#xff09;、纯粹循环数量&#xff08;少用&#xff09; 二、用法 1.用法1&#xff1a;简单循环&#xff08;遍历…

Activiz 9.2 for Linux Crack

Activiz 9.2 在 C#、.Net 和 Unity 软件中为您的 3D 内容释放可视化工具包的强大功能。 ActiViz 允许您轻松地将 3D 可视化集成到您的应用程序中。 ActiViz 功能 用 C# 封装的 3D 可视化软件系统 允许在 .NET 环境中快速开发可投入生产的交互式3D 应用程序 支持窗口演示基础 (…

SI3262:国产NFC+MCU+防水触摸按键三合一SoC芯片

目录 SI3262简介特点结构框图芯片特性 SI3262简介 Si3262是高度集成ACD低功耗MCUNFC15通道防水触摸按键的SoC芯片。 其MCU模块具有低功耗、Low Pin Count、宽电压工作范围&#xff0c;集成了13/14/15/16位精度的ADC、LVD、UART、SPI、I2C、TIMER、WUP、IWDG、RTC、TSC等丰富的…

紫光展锐6nm国产5G处理器T820_国产手机芯片5G方案

紫光展锐T820是一款采用先进6nm EUV工艺的芯片&#xff0c;采用134三丛集八核心CPU架构&#xff0c;由1个主频为 2.7GHz 的 Arm Cortex-A76 大核和 3个主频为2.3GHz 的Arm Cortex-A76大核以及4个主频为2.1GHz的 Arm Cortex-A55组成 &#xff0c;支持高达3MB 三级缓存&#xff0…

jvm内存分配与回收策略

自动内存管理 解决两个问题 自动给对象分配内存 对象一般堆上分配&#xff08;而实际上也有可能经过即时编译后被拆散为标量类型并间接地在栈上分配&#xff09; 新生对象通常会分配在新生代&#xff0c;少数情况下&#xff08;例如对象大小超过一定阈值&#xff09;也可能…

[C++网络协议] 优于select的epoll

1.epoll函数为什么优于select函数 select函数的缺点&#xff1a; 调用select函数后&#xff0c;要针对所有文件描述符进行循环处理。每次调用select函数&#xff0c;都需要向该函数传递监视对象信息。 对于缺点2&#xff0c;是提高性能的最大障碍。因为&#xff0c;套接字是…

Python爬虫实战案例——第六例

文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff01;严禁将文中内容用于任何商业与非法用途&#xff0c;由此产生的一切后果与作者无关。若有侵权&#xff0c;请联系删除。 目标&#xff1a;去哪儿网指定城市人气值最高的15个景点评论数据采集 地址&a…