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

[C++]set和map的介绍及使用

        关于set和map的接口函数部分,只重点介绍一些相较于别的容器有特殊地方的接口,set和map的接口可以触类旁通。

一、概念

(一)、关联式容器

        关联式容器存储的元素是一个个的键值对<key,value>通过键(key)可以快速索引到其对应的value值。关联容器可以快速查找、读取或者删除所存储的元素,同时该类型的容器插入元素的效率比序列容器(如vector)高。

(二)、键值对

        键值对用来表示具有一一对应关系的一种结构,该结构中只包含两个成员变量key和value,key代表键值,value表示与key对应的信息,可以通过键值key快速索引到其对应的信息value。比如说英汉词典,查询单词的中文释义就需要通过英文单词快速索引到中文释义,这里的键key是英文单词,key的类型为string,key对应的信息value是中文释义,value的类型也为string,这样,英文单词和中文释义就构成了一个<string,string>的键值对。

        键值对可以用pair类来表示,pair是C++的STL提供的一个类。pair - C++ Reference (cplusplus.com)icon-default.png?t=N7T8https://legacy.cplusplus.com/reference/utility/pair/        pair存储了公有的两个成员变量,一个叫做first,一个叫做second,可以在外部访问,这两个成员变量的类型通过用户指定。我们可以用pair的first存储键key,用second存储key对应的信息value。

(三)、关联式容器的结构

        根据应用场景的不同,STL总共实现了两种不同结构的关联式容器:树型结构与哈希结构。树型结构的关联式容器主要有四种:map、set、multimap、multiset。这四种容器的共同点是:使用平衡二叉搜索树(红黑树)作为其底层结果,容器中的元素是一个有序的序列,迭代器遍历得到的是一个有序的序列。

二、set和multiset

(一)set

set - C++ Reference (cplusplus.com)icon-default.png?t=N7T8https://legacy.cplusplus.com/reference/set/set/

set的简介

模板类型

template <

           class T,                                        // set::key_type/value_type

           class Compare = less<T>,         // set::key_compare/value_compare

           class Alloc = allocator<T>         // set::allocator_type

               >

T:set存储的元素类型。

Compare:仿函数,用于提供元素之间的比较方法。

Alloc:空间配置器

1、set是按照特定次序存储的没有重复元素的容器。

2、在set中,一个元素value就对应其本身的值(value本身就是键key,类型为T),并且每个元素在set中必须是不能重复的set中元素的值在容器中不能被再次修改(元素的类型总是const类型),但是可以从容器中插入或删除。

3、在内部,set中的元素总是按照其内部比较对象(类型为Compare)所指示的特定严格弱排序标准进行排序。

4、set容器在通过key访问单个元素时通常比unordered_set容器慢,但set迭代到的序列是有序的。

5、set通常以平衡二叉搜索树的形式实现。

set的接口

1、插入insert

        对于set的insert,第一个(single element)和第三个(range)版本的插入最常用,而中间的第二个(with hint)版本不是很常用,这个接口并不是在指定位置插入,而是在插入时提供一个接近最终插入的位置的迭代器,对插入元素时的效率进行优化,但这种优化效果并不总是显著的,因为用户提示不好,则会忽略用户的提示从头开始搜索插入位置进行插入,且红黑树的平衡性会影响搜索提示时的效率。

        注意到第一个(single element)版本的insert的返回值不是指向新插入位置的迭代器,而是pair<iterator,bool>类型。因为set中的元素都是唯一的,set不允许插入已经存在的元素,若插入的元素存在时,则插入失败,将返回一个pair<iterator,bool>的对象,其first成员为指向set中现有元素位置的迭代器,second成员bool值为false表示插入失败若插入的元素不存在,其first成员为指向新插入元素位置的迭代器,second成员bool值为true,表示插入成功。

代码例子:

#include <iostream>
#include <set>
using namespace std;int main()
{set<int> s;int arr[] = { 2,3,5,6,7,1,2,0,5};//将arr的元素依次插入到s中for (auto e : arr){auto ret = s.insert(e);if (ret.second == false)//插入失败{cout << *(ret.first) << "已存在,插入失败。" << endl;}}//打印s的元素for (auto e : s){cout << e << " ";}return 0;
}

运行结果: 

2已存在,插入失败。
5已存在,插入失败。
0 1 2 3 5 6 7

2、查找并计数count
        这个函数的功能是在容器中搜索与val相等的元素,并返回匹配次数。因为每个元素在set中都是唯一的,所以返回值只能为0和1。如果只想查找某个元素在不在set容器内,可以考虑不使用find函数而使用count函数,如果返回值为1,那么存在,为0则不存在。

代码例子:

int main()
{set<int> s;int arr[] = {1,2,3,4,5,6,7,8,9,10};for (auto e : arr){s.insert(e);}//查找某个值在不在s中int x;//方法1:使用find函数cin >> x;auto it = s.find(x);if (it != s.end())cout << *it << "存在!" << endl;elsecout << x << "不存在" << endl;cout << endl;//方法2,使用count函数cin >> x;if (s.count(x))cout << x << "存在" << endl;elsecout << x << "不存在" << endl;return 0;
}
3、lower_bound和upper_bound

lower_bound:得到下界

        指定一个值x,返回一个迭代器,该迭代器指向容器中的第一个满足条件的元素,条件是该元素大于或等于x。如果使用默认比较类型 (less) 实例化 set 类,则该函数将返回一个迭代器,该迭代器指向的值不小于x。

upper_bound:得到上界

        指定一个值y,返回一个迭代器,该迭代器指向容器中的第一个满足条件的元素,条件是该元素大于y。如果使用默认比较类型 (less) 实例化 set 类,则该函数将返回一个迭代器,该迭代器指向的值大于y。

        通过上面两个函数可以获得到两个迭代器,当x < y 时,这两个迭代器维护一个区间,区间范围是[x,y),左闭右开,可以用于删除指定范围的子序列。

代码例子:

int main()
{std::set<int> myset;std::set<int>::iterator itlow, itup;for (int i = 1; i < 10; i++) myset.insert(i * 10); // 10 20 30 40 50 60 70 80 90//删除区间位于 [25,65) 的元素 itlow = myset.lower_bound(25);     //找到第一个大于等于25的元素,这里是30itup = myset.upper_bound(65);      //找到第一个大于65的元素,这里是70 //删除对应迭代器区间的元素[itlow,itup)myset.erase(itlow, itup);                     // 10 20 70 80 90std::cout << "myset contains:";for (std::set<int>::iterator it = myset.begin(); it != myset.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;
}

运行结果:

myset contains: 10 20 70 80 90
 

 4、equal_range

        功能:指定一个值val,返回一对迭代器,该迭代器维护着一段区间,该区间内的元素的值都为相同,为val。由于set的元素是唯一的,所以该区间内最多只能有一个元素。若val值不存在,两个迭代器都指向位于val之后的第一个元素。

代码例子:

int main()
{std::set<int> myset;for (int i = 1; i <= 5; i++) myset.insert(i * 10);   // myset: 10 20 30 40 50std::pair<std::set<int>::const_iterator, std::set<int>::const_iterator> ret;ret = myset.equal_range(30);std::cout << "the lower bound points to: " << *ret.first << '\n';std::cout << "the upper bound points to: " << *ret.second << '\n';return 0;
}

运行结果: 

the lower bound points to: 30
the upper bound points to: 40

 

(二)multiset

multiset - C++ Reference (cplusplus.com)icon-default.png?t=N7T8https://legacy.cplusplus.com/reference/set/multiset/        multiset功能和set相似,但是multiset允许元素有冗余,可以存储多个相同的元素,而set里的每个元素都是唯一的。这里直接介绍multiset和set使用上的不同。

1、insert

        因为multise允许有重复的数据,所以用insert插入数据时不会存在插入失败的情况,其返回值不是pair<iterator,bool>类型,而直接就是iterator类型。

2、erase

        如果通过erase删除值为value的元素,那么在容器中所有与value相等的元素都会被删除。

代码例子:

int main()
{multiset<int> myMultiset;int arr[] = { 10,10,20,20,20,30,40,50,60 };for (auto e : arr){myMultiset.insert(e);}for (auto e : myMultiset){cout << e << " ";}cout << endl;cout << "删除20" << endl;myMultiset.erase(20);for (auto e : myMultiset){cout << e << " ";}return 0;
}

运行结果: 

10 10 20 20 20 30 40 50 60
删除20
10 10 30 40 50 60

3、count 

        由于元素在multise中不再唯一,count的返回值是大于等于0的。

int main()
{multiset<int> myMultiset;int arr[] = { 10,10,20,20,20,30,40,50,60 };for (auto e : arr){myMultiset.insert(e);}for (auto e : myMultiset){cout << e << " ";}cout << endl;cout << "20出现了" << myMultiset.count(20) << "次" << endl;return 0;
}

运行结果: 

10 10 20 20 20 30 40 50 60
20出现了3次
 

4、lower_bound和upper_bound

        功能和上面介绍的set的lower_bound和upper_bound一样,不过lower_bound和upper_bound在multiset用得更多一些。

代码例子:

int main()
{multiset<int> myMultiset;int arr[] = { 10,10,20,20,20,30,40,50,60,60,60,70,80,90,100};//插入数据for (auto e : arr){myMultiset.insert(e);}//打印for (auto e : myMultiset){cout << e << " ";}cout << endl;//删除区间位于 [25,65) 的元素 auto itlow = myMultiset.lower_bound(25);     //找到第一个大于等于25的元素,这里是30auto itup = myMultiset.upper_bound(65);      //找到第一个大于65的元素,这里是70 myMultiset.erase(itlow, itup);for (auto e : myMultiset){cout << e << " ";}return 0;
}

运行结果:

10 10 20 20 20 30 40 50 60 60 60 70 80 90 100
10 10 20 20 20 70 80 90 100

 5、equal_range

        功能和上面介绍的set的equal_range一样,不过equal_range在multiset用得更多一些,可以得到一个迭代器区间,该区间内的元素都和指定key相同。

代码例子:

int main()
{multiset<int> myMultiset;int arr[] = { 10,10,20,20,20,30,40,50,60,60,60,70,80,90,100 };//插入数据for (auto e : arr){myMultiset.insert(e);}//打印for (auto e : myMultiset){cout << e << " ";}cout << endl;//得到重复元素60的迭代器区间pair<multiset<int>::iterator, multiset<int>::iterator> ret = myMultiset.equal_range(60);//删除myMultiset.erase(ret.first, ret.second);//打印for (auto e : myMultiset){cout << e << " ";}cout << endl;return 0;
}

运行结果:

10 10 20 20 20 30 40 50 60 60 60 70 80 90 100
10 10 20 20 20 30 40 50 70 80 90 100

三、map和multimap

(一)map

map - C++ Reference (cplusplus.com)icon-default.png?t=N7T8https://legacy.cplusplus.com/reference/map/map/

map的简介

模板类型

template <

           class Key,                                     // map::key_type

           class T,                                       // map::mapped_type

           class Compare = less<Key>,                     // map::key_compare

           class Alloc = allocator<pair<const Key,T> >    // map::allocator_type

           >

key:键key的类型。

T:映射值value的类型。

Compare: 比较器的类型,map中的元素是按照key来比较的,缺省情况下按照小于来比较,一般情况下(内置类型元素)该参数不需要传递,如果无法比较时(自定义类型),需要用户自己显式传递比较规则(一般情况下按照函数指针或者仿函数来传递)

Alloc:空间配置器

1、map是一种关联容器,用于存储由键key和映射值value组合而成的元素,按照特定顺序存储。

2、在map中,键值通常用于对元素进行排序和唯一标识,而映射值存储与此键相关的内容。键和映射值的类型可以不同,键和映射值在成员中用一个value_type类型的变量组合在一起,value_type是将两者组合在一起的pair类型:typedef pair<const Key, T> value_type;

3、在内部,映射中的元素总是按照其内部比较对象(类型为Compare)所指示的特定严格弱排序标准的键进行排序。

4、map容器在通过键key访问单个元素时通常比unordered_map容器慢,但map迭代到的序列是有序的。

5、map中的映射值value可以使用括号操作符((operator[])通过对应的键key直接访问到。

6、map通常以二叉搜索树的形式实现。

map的接口 

1、插入insert

        map存储的元素类型是pair<K,V>类型,插入元素时需要传入pair<K,V>类型的对象进行插入。

插入例子:

void test1()
{//英汉词典map<string, string> dict;//插入方法1:实例化pair对象插入pair<string, string> kv1("abandon", "v.放弃");dict.insert(kv1);//插入方法2:构造函数生成匿名对象dict.insert(pair<string, string>("ability", "n. 能力; 才能"));//插入方法3:使用make_pair函数返回pair类型变量dict.insert(make_pair("able", "a. 能够;有能力的"));//插入方法4:多参数构造函数的类型转换pair<string, string> kv2 = { "abnormal"," a. 不正常的" };dict.insert(kv2);dict.insert({ "abnormal"," a. 不正常的" });//插入方法5: 初始化列表initializer_list + 多参数构造函数的类型转换initializer_list<pair<const string, string>> l = { {"aboard","ad.在船、飞机上"} ,{"abolish","v.废除"},{"about","ad. 大约;到处;四处"} };dict.insert(l);dict.insert({ {"aboard","ad.在船、飞机上"} ,{"abolish","v.废除"},{"about","ad. 大约;到处;四处"} });//打印词库for (auto& e : dict){cout << e.first << " -> " << e.second << endl;}
}void test2()
{//插入方法5: 初始化列表initializer_list + 多参数构造函数的类型转换//一步到位//英汉词典map<string, string> dict = { {"abandon", "v.放弃"},{"ability", "n. 能力; 才能"},{"abnormal"," a. 不正常的"},{"aboard","ad.在船、飞机上"},{"abolish","v.废除"},{"about","ad. 大约;到处;四处"}};//打印词库for (auto& e : dict){cout << e.first << " -> " << e.second << endl;}
}int main()
{test1();cout << endl;test2();return 0;
}

运行结果:

abandon -> v.放弃
ability -> n. 能力; 才能
able -> a. 能够;有能力的
abnormal ->  a. 不正常的
aboard -> ad.在船、飞机上
abolish -> v.废除
about -> ad. 大约;到处;四处

abandon -> v.放弃
ability -> n. 能力; 才能
abnormal ->  a. 不正常的
aboard -> ad.在船、飞机上
abolish -> v.废除
about -> ad. 大约;到处;四处
 

2、下标访问operator[]和at

        功能:使map可以像数组通过下标访问到数据一样,通过对应的键key访问到其对应映射的值value。

        如果key与容器中元素的键匹配,则该函数将返回对其映射值的引用。
        如果key与容器中任何元素的键不匹配,则该函数将插入一个该键的新元素,并返回对其映射值的引用。请注意, 本操作会让容器大小增加 1,即使没有为该元素分配映射值来初始化(该新元素会在构造时使用映射值类型的默认构造进行初始化),

        功能:和operator[]功能类似,通过键key访问其映射值,返回key对应的映射值的引用。但是,如果键key不存在,则会抛异常。 

代码例子:

int main()
{//统计选民的投票次数string arr[] = { "张三","李四","张三","李四","王某","王某","李四","李四","王某" };//键:名字 映射值:投票次数map<string, int> count;//计数for (auto& e : arr){//通过名字索引对应的投票次数并加一,代表投票次数加一//如果该名字不在count里,则用该名字作为key新插入一个元素,其映射值使用的是int内置类型的默认构造,其值为0count[e]++; }//打印选民和对应的投票次数for (auto e : count){cout << e.first << " -> " << e.second << endl;}return 0;
}

运行结果:

李四 -> 4
王某 -> 3
张三 -> 2
 

3、其他接口

        map的count、lower_bound、upper_bound以及equal_range的功能和set的是一样的,其功能在set部分已经着重介绍过了,这里不再赘述。 

(二)、multimap

        multimap和map功能类似,这里也不再赘述。需要注意的是multimap允许元素冗余,容器中可以存在多个相同key的元素,并且multimap中没有重载operator[]和at操作,因为multimap中可以有多个相同的key对应不同的映射值,使用operator[]的话返回值的类型应该是一个引用映射值的数组,这样的话会使内存更加复杂化,如果需要得到所有相同key的元素,可以通过equal_range得到这个集合的迭代器区间,这样更加简洁。

相关文章:

[C++]set和map的介绍及使用

关于set和map的接口函数部分&#xff0c;只重点介绍一些相较于别的容器有特殊地方的接口&#xff0c;set和map的接口可以触类旁通。 一、概念 &#xff08;一&#xff09;、关联式容器 关联式容器存储的元素是一个个的键值对<key,value>。通过键&#xff08;key&#x…...

【MySQL】MySQL学习笔记(持续更新)

1. 安装MySQL&#xff08;windows环境&#xff09; &#xff08;1&#xff09;在http://www.mysql.com下载*.msi的安装文件&#xff0c;并运行安装&#xff1a; 如&#xff1a;mysql-installer-community-8.0.39.0.msi 全部安装包含如下内容&#xff1a; …...

ArcGIS如何将投影坐标系转回为地理坐标系

有时候两个数据&#xff0c;一个为投影坐标系&#xff0c;另一个为地理坐标系时&#xff0c;在GIS软件中位置无法叠加到一起&#xff0c;这需要将两个或多个数据的坐标系统一&#xff0c;可以直接将地理坐标系的数据进行投影&#xff0c;或将投影坐标系转为地理坐标系。下面介绍…...

Parallels Desktop 19 for Mac 安装虚拟机需要激活吗

Parallels Desktop 19 for Mac 乃是一款适配于 Mac 的虚拟化软件。它能让您在 Mac 计算机上同时运行多个操作系统。您可借此创建虚拟机&#xff0c;并于其中装设不同的操作系统&#xff0c;如 Windows、Linux 或 macOS。使用 Parallels Desktop 19 mac 版时&#xff0c;您可在 …...

wps题注为表格或图片编号

word中为表格添加题注&#xff1a; 问题&#xff1a;多次或多人编辑导致--序号不能联动更新&#xff08;域代码不一致,如图&#xff09; 所以是否可以批量替换word里的域代码&#xff1f;如果可以这问题就解决了————失败 解决办法&#xff1a; 如图&#xff0c;复制表头&…...

集成测试怎么做?

任何产品想要长期保持高质量运行&#xff0c;集成测试正是实现这一目标必不可少的工具。 本文重点介绍集成测试实现的流程&#xff0c;而非测试工具本身。我们的目的是聚焦于创建测试过程中你可能遇到的问题&#xff0c;以便你能自主地推进工作。 缺陷的成本 细节决定成败&a…...

java mybatis 使用work id

在 MyBatis-Plus 中&#xff0c;如果你想要使用 WORK_ID 作为 ID 生成策略的一部分&#xff0c;通常是指使用雪花算法&#xff08;Snowflake Algorithm&#xff09;的一种变体来生成全局唯一 ID。雪花算法能够生成一个递增的 64 位整数作为 ID&#xff0c;这种 ID 在分布式系统…...

MySQL 的子查询(Subquery)

在数据库查询中&#xff0c;有时候我们需要从一个查询的结果集中获取数据&#xff0c;再将这些数据作为另一个查询的一部分来使用。MySQL 提供了子查询&#xff08;Subquery&#xff09;这一强大工具&#xff0c;帮助我们实现嵌套查询&#xff0c;从而解决复杂的数据检索需求。…...

后端Web之数据库(以MySQL为例)

目录 1.概述 2.MySQL 3.DDL 4.DML 5.DQL 1.概述 对于我们自己写的一些小功能&#xff0c;数据一般存储在文件中&#xff0c;比如XML文件。而在实际项目中&#xff0c;数据都是存放在数据库中的。数据库&#xff08;DataBase &#xff09;是一个存储数据的集合&#xff0c…...

委托发布 | 进迭时空联合移动云能力中心实现业界首个RISC-V IO虚拟化方案

仟江水商业电讯&#xff08;8月22日 北京 委托发布&#xff09;虚拟化是云计算技术基石&#xff0c;是RISC-V走进云计算等高性能计算场景的必然要求。RISC-V国际基金会2021年制定了Hypervisor 1.0规范&#xff0c;2023年制定了AIA 1.0规范和IOMMU 1.0规范&#xff0c;这3个规范…...

3-Electron打开新窗口,并跳转到指定的路由

需要配置路由。src/router/index.js {path: "/selectMode",name: "selectMode",component: () > import("//view/selectMode/index.vue"),},src/**.vue import { ipcRenderer } from "electron";const openNewTab () > {let p…...

comfyUI和SD webUI都有哪些差别呢?

ComfyUI和SD WebUI都是用于AI绘画的用户界面&#xff0c;它们各自有着不同的特点和适用场景。以下是两者之间的一些关键差别&#xff1a; 1、用户体验与界面友好性: SD WebUI&#xff08;Stable Diffusion Web User Interface&#xff09;以其直观易用著称&#xff0c;特别受初…...

MySql中常用的sql语句大全(工作常用篇)

1. DDL 1.1 操作数据库 --创建库 create database 库名;--创建库时判断库是否存在&#xff0c;不存在则创建 create database if no exists 库名;--查看所有数据库 show databases;--使用指定数据库 use 库名;--查看当前指定数据库包含的数据表 show tables;--查看数据库的结…...

React+Vis.js(03):vis.js设置节点形状

文章目录 Vis支持的形状类型代码实现完整代码实现效果Vis支持的形状类型 circle(圆形)box(盒子)dot(点)star(五角星)triangle(三角形)ellipse(椭圆形)triangleDown(倒三角形)diamond(菱形)代码实现 通过shape属性来定义每个节点的形状 const nodes = new vis…...

Pod和Deployment

一、pod Evicted状态&#xff1a; 在Kubernetes中&#xff0c;当节点资源紧张时&#xff0c;Kubelet可能会驱逐节点上的一些Pods以释放资源。当这种情况发生时&#xff0c;Pod的状态会被设置为"Evicted"。 1.pod的探针 1.就绪性探针&#xff1a; 一般用于探测容器…...

7. 数据结构—二叉树(链式存储)

1. 内容 包括链式存储二叉树的 递归与非递归实现的先序、中序以及后序遍历、层序遍历、创建二叉树、计算深度、总节点数。 2. 实现代码 注意&#xff1a;只是伪代码&#xff0c;如果想要运行的话在细节方面需要自己修正&#xff0c;栈和队列的方法实现需要引进或者使用其C自…...

AScript 的UI asui模板的导入

两种方案&#xff1a; 第一种直接在web端&#xff0c;右击UI文件夹 第二种在pycharm&#xff0c;也是右击UI文件夹 调用UI&#xff0c;在init类中直接调用即可...

Linux shell编程学习笔记75:sed命令——沧海横流任我行(下)

0 前言 在 Linux shell编程学习笔记73&#xff1a;sed命令——沧海横流任我行&#xff08;上&#xff09;-CSDN博客文章浏览阅读684次&#xff0c;点赞32次&#xff0c;收藏24次。在大数据时代&#xff0c;我们要面对大量数据&#xff0c;有时需要对数据进行替换、删除、新增、…...

探索Scratch中的物理世界:碰撞与重力的编程之旅

标题&#xff1a;探索Scratch中的物理世界&#xff1a;碰撞与重力的编程之旅 Scratch是一款由麻省理工学院媒体实验室开发的编程教育工具&#xff0c;它以图形化编程界面为特色&#xff0c;让初学者能够轻松地学习编程基础。Scratch不仅支持基本的编程逻辑&#xff0c;如循环、…...

大模型重塑就医体验:医联MedGPT助力健康中国建设

来源&#xff1a;新华网 2024 08/22 11:24:15 【责任编辑:吴起龙】 随着“百模大战”的加速推进&#xff0c;AI大模型的应用逐渐成为各行业关注的焦点。在这一背景下&#xff0c;医疗行业也迎来了AI技术的深度渗透。自2023年起&#xff0c;百度、科大讯飞、百川智能、商汤…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元&#xff08;GRU&#xff09;长短期记忆神经网络&#xff08;LSTM&#xff09…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...