C++:set和map的使用

目录

序列式容器和关联式容器

set

set类的介绍

构造和迭代器

增删查

insert

find和erase

erase迭代器失效

lower_bound与upper_bound

multiset和set的区别

map

map类的介绍

pair类型介绍

构造和迭代器

增删查

map数据修改:重载operator[]

multimap和map的区别


序列式容器和关联式容器

一般来说,像string、vector、list、deque、forward_list等容器,这些容器的底层逻辑机构为线性序列的数据结构,所以这些容器也叫做序列式容器,序列式容器两个位置存储的值之间一般没有紧密的关联关系,如若将其交换,依旧是序列式容器。序列式容器中的元素是按他们在容器中的存储位置保存和访问的。

与之相反,关联式容器逻辑结构通常是非线性的两个位置有紧密的关联关系,不允许交换,因为会破坏存储结构。关联式容器中的元素是按照关键字来保存和访问的。

关联式容器有map/set系列unordered_set/unordered_map系列map和set的底层是红黑树(二叉搜索树)set是key搜索场景的结构map是key/value搜索场景的结构

set

set类的介绍

template < class T,                    // set::key_type/value_typeclass Compare = less<T>,    // set::key_compare/value_compareclass Alloc = allocator<T>  // set::allocator_type 空间配置器> class set;

说明:

1.T就是set底层关键字key的类型。

2。set默认支持(不传参)是小于比较,如果有需求,可更改传入的仿函数。

3.set底层存储数据的内存是从空间配置器申请的,如果有特别需要可以自己实现内存池传入。

4.一般而言,我们只需传入第一个参数,后两个参数不需要手动传。

5.set的底层是红黑树增删查的效率是O(logN),迭代且走的是树的中序遍历,得到的结果是有序的。

template < class T,                    // set::key_type/value_typeclass Compare = less<T>,    // set::key_compare/value_compareclass Alloc = allocator<T>  // set::allocator_type 空间配置器> class set;//1.单个数据插入,如果已经存在则插入失败 
pair<iterator, bool> insert(const value_type& val);//2.列表插入,已经在容器中存在的值不会插入 
void insert(initializer_list<value_type> il);//3.迭代器区间插入,已经在容器中存在的值不会插入 
template <class InputIterator>
void insert(InputIterator first, InputIterator last);//查找val,返回val所在的迭代器,没有找到返回end() 
iterator find(const value_type& val);//查找val,返回Val的个数 
size_type count(const value_type& val) const;//1.删除一个迭代器位置的值 
iterator erase(const_iterator position);//2.删除val,val不存在返回0,存在返回1 
size_type erase(const value_type& val);//3.删除一段迭代器区间的值 
iterator erase(const_iterator first, const_iterator last);//返回大于等于val位置的迭代器 
iterator lower_bound(const value_type& val) const;//返回大于val位置的迭代器 
iterator upper_bound(const value_type& val) const;

set是key结构, map才是key/value结构, 这里的key_type和value_type是为了保持与map一致,所以才有了value_type,在set中其实就是key,当然key_type也是key。

构造和迭代器

 1.set的构造有无参默认构造迭代器区间构造拷贝构造列表构造

2.set的迭代器是双向迭代器,支持正向和反向遍历,但要注意的是,无法通过迭代器修改数据,这样会破坏搜索树的结构。

void test_set1()
{vector<int> v({1,5,4,2,3,6,7,8,9});set<int> s1;                          //无参认构造set<int> s2(v.begin(), v.end());      //迭代器区间构造set<int> s3(s2);                      //拷贝构造set<int> s = { 1,5,4,2,3,6,7,8,9 };   //列表初始化构造//1.正向迭代器for (auto e : s2){cout << e << " ";}cout << endl;//set<int>::iterator it = s2.begin();auto it = s2.begin();while (it != s2.end()){cout << *it << " ";++it;}cout << endl;//2.set是双向迭代器迭代器支持++/--,但是不是随机迭代器不支持+/-it = --s2.end();auto end = --s2.begin();while (it != end){cout << *it << " ";--it;}cout << endl;//3.反向迭代器//auto rit = s2.rbegin();set<int>::reverse_iterator rit = s2.rbegin();while (rit != s2.rend()){cout << *rit << " ";++rit;	}cout << endl;}

增删查

set支持增删查,但不支持修改,会破坏红黑树的结构。

set不支持插入相同的数据,但是multiset支持插入相同的数据。

insert

//1.单个数据插入,如果已经存在则插入失败 
pair<iterator, bool> insert(const value_type& val);//2.列表插入,已经在容器中存在的值不会插入 
void insert(initializer_list<value_type> il);//3.迭代器区间插入,已经在容器中存在的值不会插入 
template <class InputIterator>
void insert(InputIterator first, InputIterator last);

删除具体的值返回size_type而不是bool是为了与multiset保持一致,multiset含有重复数据(例如:multiset中有3个5,若要删除5,则返回值就是3) 

void test_set2()
{vector<int> v({ 7,6,8 });//1.单个数据插入,如果已经存在则插入失败 set<int> s1;s1.insert(3);s1.insert(3);s1.insert(1);s1.insert(2);//2.插入列表,同理如果已经存在则该数据插入失败s1.insert({ 4, 6, 5, 4 });//3.插入迭代器区间s1.insert(v.begin(), v.end());set<int> s2;s2.insert(3);s2.insert(2);s2.insert(1);s2.insert(5);s2.insert(4);s2.insert(5);set<int>::iterator it = s2.begin();while (it != s2.end()){cout << *it << " "; //输出1 2 3 4 5++it;}cout << endl;//单参数支持隐式类型转换:构造tmp+用tmp拷贝构造strs1——>优化为直接构造strs1set<string> strs1 = { "white", "blue", "black" };//调用默认构造set<string> strs2({ "white", "blue", "black" });//遍历strs1比较ascll码大小顺序遍历的for (auto& e : strs1){cout << e << " ";}cout << endl;
}

find和erase

find在算法库也有,适用于各种容器,时间复杂度为O(n)。

auto pos1 = find(s.begin(), s.end(), x);

set自己的find是利用二叉搜树进行查找,时间复杂度 O(logN)

auto pos2 = s.find(x);
//1.删除一个迭代器位置的值 
iterator erase (const_iterator position);//2.删除val,val不存在返回0,存在返回1
size_type erase (const value_type& val);//3.删除⼀段迭代器区间的值 
iterator erase (const_iterator first, const_iterator last);//查找val,返回val所在的迭代器,没有找到返回end() 
iterator find (const value_type& val);//查找val,返回Val的个数 
size_type count (const value_type& val) const;
void test_set3()
{set<int> s = { 3, 2, 1, 5, 6, 7, 8, 9 , 11, 13, 12, 15, 14};//1.迭代器删除最小值s.erase(s.begin());//2.删除具体的值val:底层就是find+迭代器删除int x;cin >> x;int num = s.erase(x);if(num)cout << x << "删除成功!" << endl;elsecout << x << "不存在!" << endl;//3.删除一段迭代器区间的值,注意是左闭右开区间auto first = s.find(5);auto last = s.find(7);s.erase(first, last);for (auto e : s)cout << e << " ";cout << endl;//find+迭代器删除int y;cin >> y;//找到返回该值的迭代器,找不到返回s.end()auto pos = s.find(y);if (pos != s.end())s.erase(pos);elsecout << y << "不存在!" << endl;//利用count间接实现快速查找int z;cin >> z;if(s.count(z))cout << z << "存在!" << endl;elsecout << z << "不存在!" << endl;
}

erase迭代器失效

void test_set4()
{set<int> s = { 1, 3, 4 ,6, 5, 2 };auto pos = s.find(4);//pos位置的迭代器失效//s.erase(pos);//cout << *pos << endl; //强行访问导致程序崩溃//正确做法,erase会返回删除元素的下一个元素,更新pospos = s.erase(pos);//4的下一个元素是5cout << *pos << endl;//注意,若查找的是6的话,那么删除6后迭代器pos就变成了s.end(),此时访问程序崩溃}

lower_bound与upper_bound

//返回大于等于val位置的迭代器:按照搜索树的规则找
iterator lower_bound(const value_type& val) const;//返回大于val位置的迭代器:按照搜索树的规则找
iterator upper_bound(const value_type& val) const;
void test_set5()
{set<int> s1;for (int i = 1; i < 10; i++){s1.insert(i * 10); //10 20 30 40 50 60 70 80 90}set<int> s2(s1);cout << endl;//要求:删除[30, 60]区间的值//1.erase的迭代器区间删除左闭右开:[)auto first = s1.find(30);auto last = s1.find(70);s1.erase(first, last);for (auto e : s1){cout << e << " "; //10 20 70 80 90}cout << endl;//要求:删除[25, 55]区间的值,那就要找到30 60位置的迭代器,但上面的方法无效,因为find查找不到,返回的是s.end()迭代器//此时需要用到lower_bound和upper_boundauto itlow = s2.lower_bound(25); //返回 >= 25的迭代器:就是30位置的迭代器auto itup = s2.upper_bound(55);  //返回 > 55的迭代器:就是60位置的迭代器s2.erase(itlow, itup);for (auto e : s2){cout << e << " "; //10 20 60 70 80 90}cout << endl;}

multiset和set的区别

multiset与set的使用基本类似,主要区别在于multiset支持冗余插入,那么insert/find/count/erase就会有所区别。

void test_set6()
{//相比set不同的是,multiset是排序,但是不去重 multiset<int> mulset = { 4,2,7,2,4,8,4,5,4,9 };auto it = mulset.begin();while (it != mulset.end()){cout << *it << " "; //输出:2 2 4 4 4 4 5 7 8 9++it;}cout << endl;//x可能会存在多个,find查找中序的第一个 int x;cin >> x;auto pos = mulset.find(x);while (pos != mulset.end() && *pos == x){cout << *pos << " ";++pos;}cout << endl;//count会返回x的实际个数 cout << mulset.count(x) << endl;//erase给值时会删除所有的x mulset.erase(x);for (auto e : mulset){cout << e << " ";}cout << endl;}

map

map类的介绍

template < class Key,                                     // map::key_typeclass T,                                       // map::mapped_typeclass Compare = less<Key>,                     // map::key_compareclass Alloc = allocator<pair<const Key,T> >    // map::allocator_type> class map;

1.Key就是map底层关键字声明,T就是map底层value的类型。

2.map默认要求Key支持小于比较,如若需要,可以手动传仿函数。

3.map底层存储数据的内存是从空间配置器申请的。

4。map底层也是红黑树,增删查改的效率是O(logN) ,注意,这里的改指的是修改ValueKey是不能修改的。

pair类型介绍

template <class T1, class T2>
struct pair
{T1 first;T2 second;//无参默认构造pair():first(T1()),second(T2()){}pair(const T1& a, const T2& b):first(a),second(b){}//拷贝构造template<class U, class V>pair(const pair<U, V>& pr):first(pr.first),second(pr.second);{}
};//创建pair对象
template <class T1, class T2>
inline ::pair<T1, T2> make_pair(T1 x, T2 y)
{return pair<T1, T2>(x, y);
}
Member types 
key_type	->  The first template parameter (Key)	
mapped_type	->  The second template parameter (T)	
value_type	->  pair<const key_type,mapped_type>

map是key/value搜索场景的结构,key_type就是key,而mapped_type就是value,而value_type才是pair。

构造和迭代器

1.mapt的构造有无参默认构造迭代器区间构造拷贝构造列表构造

2.map支持正向和反向迭代,遍历默认是升序。

//empty (1) 无参默认构造 
explicit map(const key_compare& comp = key_compare(),const allocator_type& alloc = allocator_type());//range (2) 迭代器区间构造 
template <class InputIterator>
map(InputIterator first, InputIterator last,const key_compare& comp = key_compare(),const allocator_type & = allocator_type());//copy (3) 拷贝构造 
map(const map& x);//initializer list (4) initializer 列表构造 
map(initializer_list<value_type> il,const key_compare& comp = key_compare(),const allocator_type& alloc = allocator_type());//迭代器是一个双向迭代器 
iterator->a bidirectional iterator to const value_type//正向迭代器 
iterator begin();
iterator end();//反向迭代器 
reverse_iterator rbegin();
reverse_iterator rend();
void test_map1()
{//无参默认构造map<int, int> m1;//迭代器区间构造vector<pair<int, int>> v = { {1,1}, {2, 2}, {3, 3} };map<int, int> m2(v.begin(), v.end());//拷贝构造map<int, int> m3(m2);//列表初始化构造map<int, int> m4 = { {1,1}, {2, 2}, {3, 3}, { 4, 4} };//1.正向迭代器//map<int, int>::iterator it = m4.begin();auto it = m4.begin();while (it != m4.end()){cout << it->first << " " << it->second << endl;++it;}cout << endl;//2.反向迭代器auto rit = m4.rbegin();while (rit != m4.rend()){cout << rit->first << " " << rit->second << endl; //输出:1 2 1 2++rit;}cout << endl;
}

增删查

Member types 
key_type	->  The first template parameter (Key)	//key
mapped_type	->  The second template parameter (T)	//value
value_type	->  pair<const key_type,mapped_type>    //pair//单个数据插入,如果已经key存在则插入失败,key存在相等value不相等也会插入失败 
pair<iterator, bool> insert(const value_type& val);//列表插入,已经在容器中存在的值不会插入
void insert(initializer_list<value_type> il);//迭代器区间插入,已经在容器中存在的值不会插入
template <class InputIterator>
void insert(InputIterator first, InputIterator last);//查找k,返回k所在的迭代器,没有找到返回end() 
iterator find(const key_type& k);//查找k,返回k的个数 
size_type count(const key_type& k) const;//删除一个迭代器位置的值 
iterator erase(const_iterator position);//删除k,k存在返回0,存在返回1 
size_type erase(const key_type& k);//删除一段迭代器区间的值
iterator erase(const_iterator first, const_iterator last);//返回大于等于k位置的迭代器
iterator lower_bound(const key_type& k);//返回大于k位置的迭代器
const_iterator upper_bound(const key_type& k) const;
void test_map2()
{map<string, string> dict;//插入有名对象pair<string, string> kv1("first", "第一");dict.insert(kv1);//插入匿名对象dict.insert(pair<string, string>("second", "第二"));//利用make_pair函数返回构造的pair对象,插入dict.insert(make_pair("third", "第三"));//C++11支持多参数隐式类型转换成pair对象,插入dict.insert({ "forth", "第四" });//"forth"已经存在,插入失败dict.insert({ "forth", "第四" });auto it = dict.begin();while (it != dict.end()){cout << (*it).first << " " << (*it).second << endl;//map的迭代基本都使用operator->,这里省略了一个-> //第一个->是迭代器运算符重载,返回pair*,第二个箭头是结构指针解引用取pair数据cout << it->first << " " << it->second << endl;++it;//it->first += 'x';   //key不支持修改//it->second += 'x'; // value支持修改}cout << endl;for (auto& e : dict){cout << e.first << " " << e.second << endl;}cout << endl;string str;while (cin >> str){auto ret = dict.find(str);if (ret != dict.end()){cout << "->" << ret->second << endl;}else{cout << "无此单词,请重新输入" << endl;}}//erase与set中的erase一模一样,就不做演示了
}

关于insert这个函数,它返回的是一个pair,但这pair不是map里的pair,insert返回的pair的key是map的迭代器,value是一个bool值。当你插入一个{key,value}的时候,如果插入成功返回的pair的迭代器是指向新节点的bool值为真;当插入相同值的时候,也就是插入失败的时候,返回的pair的迭代器指向的是与插入{key,value}的key相等的节点bool值为假

所以这个insert既有插入的功能也有查找的功能。

map数据修改:重载operator[]

map支持修改value,既可以通过迭代器实现,也可以通过operator[]实现的。

注意从内部实现角度,map这理把我们传统说的value值,给的是T类型,typedef为mapped_type。而value_type是红黑树结点中存储的pair键值对值。日常使用我们还是习惯将这里的T映射值叫做value。

Member types
key_type     ->  The first template parameter (Key)
mapped_type  ->  The second template parameter (T)
value_type   ->  pair<const key_type,mapped_type>
//查找k,返回k所在的迭代器,没有找到返回end(),如果找到了通过iterator可以修改key对应的mapped_type(value)值
iterator find(const key_type& k);//insert插入一个pair<key, T>对象 
//1.如果key已经在map中,插入失败,则返回一个pair<iterator,bool>对象,
//返回pair对象first是key所在结点的迭代器,second是false//2.如果key不在map中,插入成功,则返回一个pair<iterator,bool>对象,
//返回pair对象first是新插入key所在结点的迭代器,second是true//也就是说无论插入成功还是失败,返回pair<iterator,bool>对象的first都会指向key所在的迭代器
//那么也就意味着insert插入失败时充当了查找的功能,正是因为这一点,insert可以用来实现operator[]//需要注意的是这里有两个pair,不要混淆了,
//一个是map底层红黑树节点中存的pair<key, T>,
//另一个是insert返回值pair<iterator, bool>
pair<iterator, bool> insert(const value_type& val);
mapped_type& operator[] (const key_type& k);//operator的内部实现 
mapped_type& operator[] (const key_type& k)
{//1.如果key不在map中,insert会插入key和mapped_type(value)的默认值,同时[]返回结点pair<iterator,bool>中存储//中的迭代器中存储的mapped_type(value)值的引用,那么我们可以通过引用修改返映射值。所以[]具备了插入 + 修改功能//2.如果k在map中,insert会插入失败,但是insert返回pair对象的first是指向与key值相同的结点的//迭代器,同时[]返回结点中存储mapped_type(value)值的引用,所以[]具备了查找 + 修改的功能pair<iterator, bool> ret = insert({ k, mapped_type() });iterator it = ret.first;return it->second;
}
void test_map3()
{map<string, string> dict;dict.insert({ "sort", "排序" });//insert不存在:插入{"insert", string()}dict["insert"];//left不存在:插入+修改dict["left"] = "左边";//left存在:修改 将"左边"修改为"左边、剩余"dict["left"] = "左边、剩余";//left存在:查找,确认left在才能这么用,否则就是插入了//输出:左边、剩余cout << dict["left"] << endl;//right不存在:插入//输出:什么都没有cout << dict["right"] << endl; }
void test_map4()
{//统计水果出现的次数 string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜","苹果", "香蕉", "苹果", "香蕉" };map<string, int> cntMap;//利用find和iterator修改功能,统计水果出现的次数 for (const auto& str : arr){//先查找水果在不在map中 //1、不在,说明水果第一次出现,则插入{水果, 1} //2、在,则查找到的节点中水果对应的次数++ auto ret = cntMap.find(str);if (ret == cntMap.end())cntMap.insert({ str, 1 });elseret->second++;}//利用[]插入+修改功能,巧妙实现统计水果出现的次数 for (auto& str : arr){//先查找水果在不在map中 //1、不在,说明水果第一次出现,则插入{水果, 1} //2、在,则查找到的节点中水果对应的次数++cntMap[str]++;}for (auto& e : cntMap){//输出苹果:6//    西瓜:3//    香蕉 : 2cout << e.first << ":" << e.second << endl;}
}

multimap和map的区别

multimap和map的使用基本完全类似,主要区别点在于multimap支持关键值key冗余,而insert/find/count/erase也是key冗余有所差异,这里跟set和multiset完全一样,比如find时,有多个key,返回中序第一个。

其次就是multimap不支持[],因为支持key冗余,[]就只能支持插入了,不能支持修改(因为key有重复,所以不知道修改哪个value)。

int main()
{multimap<string, string> dict;//插入一定成功dict.insert({ "sort", "排序" });dict.insert({ "sort", "排序1" });dict.insert({ "sort", "排序2" });dict.insert({ "sort", "排序3" });dict.insert({ "sort", "排序" });dict.insert({ "string", "字符串" });//将sort全部删除dict.erase("sort");return 0;
}

拜拜,下期再见😏

摸鱼ing😴✨🎞

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

达梦dsc环境dcr vote磁盘大小

达梦dsc环境中磁盘管理通过asm来实现&#xff0c;必须创建dcr和vote磁盘&#xff0c;那么这两个asm磁盘大小最小是多少&#xff1f; 32M asm文件最小为4个au&#xff0c;au大小为1M&#xff0c;因此asm文件最小为4M。但是创建vote时&#xff0c;命令只支持最小32M 通常生产环…

python操作MySQL以及SQL综合案例

1.基础使用 学习目标&#xff1a;掌握python执行SQL语句操作MySQL数据库软件 打开cmd下载安装 安装成功 connection就是一个类&#xff0c;conn类对象。 因为位置不知道&#xff0c;所以使用关键字传参。 表明我们可以正常连接到MySQL 演示、执行非查询性质的SQL语句 pytho…

鸿蒙进阶-AlphabetIndexer组件

大家好&#xff0c;这里是鸿蒙开天组&#xff0c;今天我们来学习AlphabetIndexer组件&#xff0c;喜欢就点点关注吧&#xff01; 通过 AlphabetIndexer 组件可以与容器组件结合&#xff0c;实现导航联动&#xff0c;以及快速定位的效果 核心用法 AlphabetIndexer不是容器组件…

Mac电脑技巧:适用于Mac的免费外置硬盘数据恢复软件

“我有一个 1 TB 的外置硬盘&#xff0c;它被意外格式化了。我尝试从中恢复丢失的数据。我把它连接到我的Mac&#xff0c;但里面什么也没找到。我正在寻找适用于Mac的免费外置硬盘数据恢复软件&#xff0c;例如奇客数据恢复Mac版或其他Mac数据恢复免费软件来扫描它并恢复数据。…

推荐一款高级的安装程序打包工具:Advanced Installer Architect

AdvanCEd Installer Architect是一款高级的安装程序打包工具&#xff0c;我们有时候可能用nsis用的多&#xff0c;Advanced Installer Architect也是一款打包工具&#xff0c;有兴趣的朋友也可以试试。有了Advanced Installer Architect你就可以创建MSI打包。 主要功能 *先进的…

LeetCode 热题100(七)【链表】(1)

7.链表 7.1相交链表&#xff08;简单&#xff09; 题目描述&#xff1a;leetcode链接 160.相交链表 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 图示两个链表在节点 c…

OpenAI正在与台积电(TSMC)和博通(Broadcom)合作,打造自己的AI推理芯片

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

小新学习k8s第四天之发布管理

一、金丝雀发布&#xff08;灰度发布&#xff09; Deployment控制器支持自定义控制更新过程中的滚动节奏&#xff0c;如“暂停(pause)”或“继续(resume)”更新操作。 ①比如等待第一批新的Pod资源创建完成后立即暂停更新过程&#xff0c;此时&#xff0c;仅存在一部分新版本的…

大数据安全方案 验证

一、背景 文档用于记录配置 Kerberos 和 Ranger 后&#xff0c;对 HDFS、Hive 认证和鉴权的功能测试。 二、Kerberos 验证 2.1、验证功能 1&#xff0c;HDFS 认证 2.1.1、访问 HDFS Kerberos 验证前&#xff0c;访问 HDFS 失败。 Kerberos 验证后&#xff0c;访问 HDFS 成…

全面解析:云计算技术及其应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 全面解析&#xff1a;云计算技术及其应用 全面解析&#xff1a;云计算技术及其应用 全面解析&#xff1a;云计算技术及其应用 云…

规范:项目、目录、文件、样式、事件、变量、方法、url参数、注释、git提交 命名规范及考证

一、规范命名的重要性 易懂、通用、规范、标准、专业性、是经验积累的体现 1.1、常见命名方法 序号命名方法解释1全小写2全大写3驼峰&#xff1a;小驼峰命名法4驼峰&#xff1a;大驼峰命名法5烤串命名法 / 脊柱命名法6下划线分隔法 二、项目名 采用小写字母和中划线&#…

03-Dubbo的负载均衡及高性能RPC调用

03-Dubbo的负载均衡及高性能RPC调用 Dubbo 的负载均衡策略 负载均衡策略就是当某个服务压力比较大的时候&#xff0c;这时候部署多个节点同时提供相同的服务 当服务消费者来消费的时候&#xff0c;可以从这多个节点中选择一个节点进行消费&#xff0c;这个选择的过程&#xff0…

【LVGL-列表部件 lv_list_create】

LVGL-列表部件 lv_list_create ■ LVGL-列表部件-函数■ 修改样式-■ 修改样式- 背景色■ 修改样式- 改变项的颜色-label■ 修改样式- 改变项的颜色-btn ■ 事件(Event)■ 示例0&#xff1a;综合■ 示例1&#xff08;自动出现滚动&#xff09;■ 示例2&#xff08;滚动捕捉&…

【React】初学React

A. react中如何创建元素呢&#xff1f; 说明一点&#xff1a; 属性都改为驼峰形式&#xff08;无障碍属性aria-*除外&#xff09;&#xff0c; class改成className 创建元素 B. 变量或表达式如何表示呢&#xff1f;大括号{ }包起来 变量值用大括号包裹 C. 元素和组件的区别 元素…

设备搜索相关协议使用

一、实现原理 首先&#xff0c;Client -> Gateway : 发送 UDP 广播包&#xff08;含厂商自定义协议)这一步表示客户端开始向网络中发送一个包含厂商自定义协议的 UDP 广播包&#xff0c;目的是寻找本厂商的设备&#xff08;网关&#xff09;。客户端此时处于活动状态activa…

TMDOG的Gin学习笔记_01——初识Gin框架

TMDOG的Gin学习笔记_01——初识Gin框架 博客地址&#xff1a;[TMDOG的博客](https://blog.tmdog114514.icu) 作者自述&#xff1a; 停更太久了&#xff0c;是因为开学了课太多了&#xff0c;并且我一直在准备上篇文章的内容正在coding&#xff0c;就先搁置了更新博客QAQ&…

H7-TOOL的CAN/CANFD助手增加帧发送成功标识支持, 继续加强完善功能细节

2.27版本固件正式携带此功能&#xff0c;包括之前做的负载率检测和错误信息展示也将集成到这个版本固件中。 对于接收&#xff0c;我们可以直接看到效果&#xff0c;而发送不行&#xff0c;所以打算在发送的地方展示下发送成功标识。CAN发送不像串口&#xff0c;需要等待应答后…

Pr 视频效果:超级键

视频效果/键控/超级键 Keying/Ultra Key 超级键 Ultra Key效果是 Premiere Pro 中功能强大的抠像工具&#xff0c;主要用于绿幕/蓝幕抠像。通过选择要抠除的颜色&#xff08;通常是绿幕或蓝幕的颜色&#xff09;&#xff0c;即可以将该颜色的像素设为透明&#xff0c;实现主体与…

善用Git LFS来降低模型文件对磁盘的占用

将讲一个实际的例子&#xff1a;对于模型文件&#xff0c;动辄就是好几个G&#xff0c;而有的仓库更是高达几十G&#xff0c;拉一个仓库到本地&#xff0c;稍不注意直接磁盘拉满都有可能。 比如&#xff1a;meta-llama-3.1-8b-instruct&#xff0c;拉到本地后发现居然占用了60G…

「树链剖分」学习笔记

一、引入 “在一棵树上进行路径的修改、求极值、求和”乍一看只要线段树就能轻松解决&#xff0c;实际上&#xff0c;仅凭线段树是不能搞定它的。我们需要用到一种貌似高级的复杂算法——「树链剖分」。 树链剖分&#xff08;简称树剖&#xff09;&#xff0c;顾名思义&#xf…