ranges::set_intersection set_union set_difference set_symmetric_difference
std::ranges::set_intersection:是 C++20 引入的一个算法,用于计算两个已排序范围的交集。它将两个范围的交集元素复制到输出范围中。
std::ranges::set_intersection
用于计算两个已排序范围的交集。它将两个范围的交集元素复制到输出范围中。
注意事项
- 输入范围必须已排序。
- 目标范围必须有足够空间存储交集结果。
- 交集结果默认按升序排列。
- 若元素重复,交集次数取两范围中较小的重复次数(例如
a = [2, 2, 3],b = [2, 2, 2],则交集为[2, 2])。
### 语法
| Defined in header | ||
| Call signature | ||
| template< std::input_iterator I1, std::sentinel_for<I1> S1, std::input_iterator I2, std::sentinel_for<I2> S2, | (1) | (since C++20) |
| template< ranges::input_range R1, ranges::input_range R2, std::weakly_incrementable O, class Comp = ranges::less, | (2) | (since C++20) |
| Helper types | ||
| template< class I1, class I2, class O > | (3) | (since C++20) |
### 参数
- `r1` 和 `r2`:输入范围,必须是已排序的。
- `result`:输出迭代器,指向存储交集元素的位置。
- `comp`:比较函数对象,用于比较元素。
- `proj1` 和 `proj2`:投影函数对象,用于投影元素。
### 返回值
返回一个 `ranges::set_intersection_result` 结构,包含两个输入范围的结束迭代器和输出范围的结束迭代器。
### 示例
以下是一个使用 `std::ranges::set_intersection` 的示例:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>void print(const auto& v, const auto& rem)
{std::cout << "{ ";for (const auto& e : v)std::cout << e << ' ';std::cout << '}' << rem;
}int main()
{const auto in1 = {1, 2, 2, 3, 4, 5, 6};const auto in2 = {2, 2, 3, 3, 5, 7};std::vector<int> out {};std::ranges::set_intersection(in1, in2, std::back_inserter(out));print(in1, " ∩ "), print(in2, " = "), print(out, "\n");
}
Output:
{ 1 2 2 3 4 5 6 } ∩ { 2 2 3 3 5 7 } = { 2 2 3 5 }
在这个示例中,`in1` 和 `in2` 是两个已排序的整数向量。`std::ranges::set_intersection` 计算它们的交集,并将结果存储在 `out` 向量中。最后,程序输出交集元素。
示例 2:自定义比较和投影
#include <algorithm>
#include <vector>
#include <iostream>
#include <string>struct Person {std::string name;int age;
};int main() {std::vector<Person> a = {{"Alice", 20}, {"Bob", 25}, {"Charlie", 30}};std::vector<Person> b = {{"Bob", 25}, {"David", 28}, {"Eve", 30}};std::vector<Person> out;// 按 age 字段比较,计算交集std::ranges::set_intersection(a, b,std::back_inserter(out),[](int age1, int age2) { return age1 < age2; }, // 比较函数&Person::age, // 对 a 的投影:提取 age&Person::age // 对 b 的投影:提取 age);// 输出结果:Bob(25), Charlie(30)for (const auto& p : out) {std::cout << p.name << "(" << p.age << ") ";}
}
更多请了解:https://en.cppreference.com/w/cpp/algorithm/ranges/set_intersection
std::ranges::set_union
std::ranges::set_union 是 C++20 引入的算法,用于合并两个已排序范围的并集,并将结果写入目标范围。
| Defined in header | ||
| Call signature | ||
| template< std::input_iterator I1, std::sentinel_for<I1> S1, std::input_iterator I2, std::sentinel_for<I2> S2, | (1) | (since C++20) |
| template< ranges::input_range R1, ranges::input_range R2, std::weakly_incrementable O, class Comp = ranges::less, |
参数说明
first1,last1:第一个输入范围的起止迭代器。first2,last2:第二个输入范围的起止迭代器。result:目标范围的起始迭代器。comp:比较函数(默认为std::ranges::less)。proj1,proj2:对输入元素的投影函数(默认为std::identity)。
要求
- 输入范围必须按
comp定义的顺序排序。 - 目标范围必须有足够空间存储并集结果。
- 重复元素处理:
- 若元素在某个范围中重复出现,并集会保留所有重复项(但不会跨范围合并)。
- 例如:
a = [2, 2, 3],b = [2, 2, 2],并集为[2, 2, 2, 3]。
- 目标空间:需确保目标范围有足够空间,或使用
std::back_inserter动态扩展。 - 性能:时间复杂度为线性(最多
2*(N1 + N2) - 1次比较,其中N1和N2为输入范围长度)。
返回值
返回指向目标范围末尾的迭代器
示例
示例 1:基本用法
#include <algorithm>
#include <vector>
#include <iostream>
#include <iterator>int main() {std::vector<int> a = {1, 2, 3, 4, 5};std::vector<int> b = {3, 4, 5, 6, 7};std::vector<int> out;// 计算并集std::ranges::set_union(a, b, std::back_inserter(out));// 输出结果:1 2 3 4 5 6 7for (int x : out) {std::cout << x << " ";}
}
输出结果:
1 2 3 4 5 6 7
示例 2:自定义比较和投影
#include <algorithm>
#include <vector>
#include <iostream>
#include <string>struct Person {std::string name;int age;
};int main() {std::vector<Person> a = {{"Alice", 20}, {"Bob", 25}, {"Charlie", 30}};std::vector<Person> b = {{"Bob", 26}, {"David", 28}, {"Eve", 30}};std::vector<Person> out;// 按 age 字段比较,计算并集std::ranges::set_union(a, b,std::back_inserter(out),[](int age1, int age2) { return age1 < age2; }, // 比较函数&Person::age, // 对 a 的投影:提取 age&Person::age // 对 b 的投影:提取 age);// 输出结果:Alice(20), Bob(25), Charlie(30), David(28), Eve(30)for (const auto& p : out) {std::cout << p.name << "(" << p.age << ") ";}
}
输出结果:
Alice(20) Bob(25) Bob(26) David(28) Charlie(30)
与传统 std::set_union 的区别
- 范围支持:直接接受范围参数(如
std::ranges::set_union(a, b, ...)),而非迭代器对。 - 投影功能:允许通过
proj1和proj2对输入元素进行变换后再比较。 - 约束检查:通过 C++20 概念明确约束参数类型,增强类型安全。
更多信息:
https://en.cppreference.com/w/cpp/algorithm/ranges/set_union
std::ranges::set_difference
| Defined in header | ||
| Call signature | ||
| template< std::input_iterator I1, std::sentinel_for<I1> S1, std::input_iterator I2, std::sentinel_for<I2> S2, | (1) | (since C++20) |
| template< ranges::input_range R1, ranges::input_range R2, std::weakly_incrementable O, class Comp = ranges::less, |
std::ranges::set_difference 是 C++20 引入的算法,用于计算两个已排序范围的差集(即存在于第一个范围但不在第二个范围中的元素),并将结果写入目标范围。它是传统 std::set_difference 的范围适配版本,支持投影和直接使用范围参数。
参数说明
first1,last1:第一个输入范围的起止迭代器(要计算差集的主范围)。first2,last2:第二个输入范围的起止迭代器(被减的范围)。result:目标范围的起始迭代器。comp:比较函数(默认为std::ranges::less)。proj1,proj2:对输入元素的投影函数(默认为std::identity)。
要求
- 两个输入范围必须按
comp定义的顺序排序。 - 目标空间:需确保目标范围有足够空间,或使用
std::back_inserter动态扩展。 - 重复元素处理:
- 若元素在第一个范围中出现
m次,在第二个范围中出现n次,则差集中保留max(m - n, 0)次。 - 例如:
a = [2, 2, 3],b = [2],差集为[2, 3]。
- 若元素在第一个范围中出现
- 性能:时间复杂度为线性(最多
2*(N1 + N2) - 1次比较,其中N1和N2为输入范围长度)。
示例
示例 1:基本用法
#include <algorithm>
#include <vector>
#include <iostream>
#include <iterator>int main() {std::vector<int> a = {1, 2, 3, 4, 5};std::vector<int> b = {3, 4, 5, 6, 7};std::vector<int> out;// 计算差集:a 中存在但 b 中不存在的元素std::ranges::set_difference(a, b, std::back_inserter(out));// 输出结果:1 2for (int x : out) {std::cout << x << " ";}
}
输出结果:
1 2
示例 2:自定义比较和投影
#include <algorithm>
#include <vector>
#include <iostream>
#include <string>struct Person {std::string name;int age;
};int main() {std::vector<Person> a = {{"Alice", 20}, {"Bob", 25}, {"Charlie", 30}};std::vector<Person> b = {{"Bob", 26}, {"David", 28}, {"Eve", 30}};std::vector<Person> out;// 按 age 字段比较,计算差集(a 中存在但 b 中不存在的元素)std::ranges::set_difference(a, b,std::back_inserter(out),[](int age1, int age2) { return age1 < age2; }, // 比较函数&Person::age, // 对 a 的投影:提取 age&Person::age // 对 b 的投影:提取 age);// 输出结果:Alice(20) Bob(25) for (const auto& p : out) {std::cout << p.name << "(" << p.age << ") ";}
}
输出结果:
Alice(20) Bob(25)
与传统 std::set_difference 的区别
- 范围支持:直接接受范围参数(如
std::ranges::set_difference(a, b, ...))。 - 投影功能:允许通过
proj1和proj2对输入元素进行变换后再比较。 - 约束检查:通过 C++20 概念明确约束参数类型,增强类型安全。
std::ranges::set_symmetric_difference
std::ranges::set_symmetric_difference 是 C++20 中引入的算法,用于计算两个有序范围的对称差集,即存在于任一输入范围但不同时存在于两个范围中的元素。结果会写入输出范围,且保持有序。
函数原型
| Defined in header | ||
| Call signature | ||
| template< std::input_iterator I1, std::sentinel_for<I1> S1, std::input_iterator I2, std::sentinel_for<I2> S2, | (1) | (since C++20) |
| template< ranges::input_range R1, ranges::input_range R2, std::weakly_incrementable O, class Comp = ranges::less, |
参数说明
first1, last1: 第一个输入范围的迭代器对。first2, last2: 第二个输入范围的迭代器对。result: 输出范围的起始迭代器。comp: 比较函数(默认为std::ranges::less)。proj1, proj2: 应用于输入元素的投影(默认为std::identity)。
使用条件
- 输入范围必须已按升序排列。
- 输出范围不能与输入范围重叠。
示例
#include <algorithm>
#include <vector>
#include <iostream>
#include <iterator>int main() {std::vector<int> v1 = {1, 2, 4, 5, 6};std::vector<int> v2 = {2, 3, 5, 7};std::vector<int> out;std::ranges::set_symmetric_difference(v1, v2, std::back_inserter(out));// 输出结果for (int n : out) {std::cout << n << ' ';}
}
输出:
1 3 4 6 7
步骤解析
- 输入准备:
v1和v2必须有序。 - 算法执行:
- 比较
v1和v2的当前元素。 - 将较小元素写入
out,移动对应迭代器。 - 若元素相等,则跳过,同时移动两个迭代器。
- 比较
- 结果:
out包含对称差集元素,保持有序。
自定义比较和投影
// 使用自定义比较函数(按降序)
std::ranges::set_symmetric_difference(v1 | std::views::reverse,v2 | std::views::reverse,std::back_inserter(out),std::greater{}
);// 使用投影(如比较字符串长度)
std::vector<std::string> s1 = {"apple", "banana", "cherry"};
std::vector<std::string> s2 = {"grape", "kiwi", "orange"};
std::ranges::set_symmetric_difference(s1, s2, std::back_inserter(out_str),[](int a, int b) { return a < b; },[](const std::string& s) { return s.length(); },[](const std::string& s) { return s.length(); }
);
总结
std::ranges::set_symmetric_difference 高效计算两个有序范围的对称差集,时间复杂度为 (O(N+M)),空间复杂度为 (O(1))(不计输出)。需确保输入有序且输出范围足够大。
相关文章:
ranges::set_intersection set_union set_difference set_symmetric_difference
std::ranges::set_intersection:是 C20 引入的一个算法,用于计算两个已排序范围的交集。它将两个范围的交集元素复制到输出范围中。 std::ranges::set_intersection 用于计算两个已排序范围的交集。它将两个范围的交集元素复制到输出范围中。 注意事项…...
在IDEA的Maven中(同步所有Maven项目)和(重新加载所有Maven项目)的区别
特性同步所有 Maven 项目 (Sync All Maven Projects)重新加载所有 Maven 项目 (Reload All Maven Projects)主要作用使 IDEA 项目结构、依赖关系与 pom.xml 文件同步。强制重新读取所有 pom.xml 文件,并重建 IDEA 的 Maven 项目模型。缓存使用 IDEA 缓存的 Maven 项…...
如何查询网站是否被百度蜘蛛收录?
一、使用site命令查询 这是最直接的方法。在百度搜索框中输入“site:你的网站域名”,例如“site.com”(请将“example.com”替换为你实际的网站域名)。如果搜索结果显示了你的网站页面,并且显示了收录的页面数量(如“…...
el-table树状表格,默认展开第一个节点的每一层
效果如图 <template><el-table:data"tableData"style"width: 100%":tree-props"{ children: children, hasChildren: hasChildren }":expand-row-keys"expandRowKeys"row-key"id"expand-change"handleExpan…...
express-validator 数据校验详解
express-validator 是一个用于在 Express 应用中进行数据验证和清理的中间件。 一、安装 # 使用 npm 安装npm install express-validator 二、基本使用 1. 引入和初始化 const express require("express");const { body, validationResult } require("ex…...
使用VSCODE开发C语言程序
使用vscode配置C语言开发环境 一、安装VSCODE 1、下载vscode 从官方网站(https://code.visualstudio.com/Download)上,下载windows版本的vscode 2、安装vscode 下载完毕后,按照提示进行安装即可(尽可能不要安…...
Python学习心得常用的内置函数
常用的内置函数: 1.数据类型转换函数: 描述说明 描述说明 bool(obj) 获取指定对象 obj 的布尔值 str(obj) 将指定对象 obj 转成字符串类型 int(x) 将 x 转成 int 类型 float(x) 将 x 转成 float 类型 list(sequence) 将序列转成列表类型 tu…...
【数据结构初阶第十二节】设计循环队列
云边有个稻草人-CSDN博客 必须有为成功付出代价的决心,然后想办法付出这个代价。 还有最后一道关于队列的习题,这题有点难,准备好迎接挑战吧! 目录 1.【题目】 2.实现循环队列推荐用数组,Why? 3.Q1:如…...
【数据分享】1929-2024年全球站点的逐年降雪深度数据(Shp\Excel\免费获取)
气象数据是在各项研究中都经常使用的数据,气象指标包括气温、风速、降水、能见度等指标,说到气象数据,最详细的气象数据是具体到气象监测站点的数据! 有关气象指标的监测站点数据,之前我们分享过1929-2024年全球气象站…...
【强化学习的数学原理】第10课-Actor-Critic方法-笔记
学习资料:bilibili 西湖大学赵世钰老师的【强化学习的数学原理】课程。链接:强化学习的数学原理 西湖大学 赵世钰 文章目录 一、最简单的Actor-Critic(QAC)二、Advantage Actor-Critic(A2C)三、重要性采样和…...
scratch猜年龄互动小游戏 2024年12月scratch四级真题 中国电子学会 图形化编程 scratch四级真题和答案解析
scratch猜年龄互动小游戏 2024年12月电子学会图形化编程Scratch等级考试四级真题 一、题目要求 老爷爷的年龄是1-100的随机数,老爷爷询问“请猜猜我的年龄是多少?”,输入年龄,老爷爷会回答"大了"或者"小了,直到最后成功猜出年龄。 1、准备工作 (1)删…...
javaSE学习笔记23-线程(thread)-总结
创建线程的三种方式 练习代码 package com.kuang.thread;import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask;//回顾总结线程的创建 public class ThreadNew {public static void main(String[…...
Boringssl介绍
BoringSSL 是 Google 从 OpenSSL 分支出来的一个开源 TLS/SSL 库,旨在为 Google 的产品和服务提供一个更加轻量、安全和现代化的加密库。它是 OpenSSL 的一个替代品,专注于简化代码、提高安全性和减少潜在的攻击面。 以下是对 BoringSSL 的详细介绍&…...
java每日精进 2.13 MySql迁移人大金仓
1.迁移数据库 1. 数据库创建语句 MySQL: CREATE DATABASE dbname; 人大金仓(Kingbase): 在人大金仓中,CREATE DATABASE 的语法通常相同,但可能需要特别注意字符集的指定(如果涉及到多语言支持…...
2025最新智能优化算法:改进型雪雁算法(Improved Snow Geese Algorithm, ISGA)求解23个经典函数测试集,MATLAB
一、改进型雪雁算法 雪雁算法(Snow Geese Algorithm,SGA)是2024年提出的一种新型元启发式算法,其灵感来源于雪雁的迁徙行为,特别是它们在迁徙过程中形成的独特“人字形”和“直线”飞行模式。该算法通过模拟雪雁的飞行…...
C++中为什么有了tuple还需要pair?
在C中,tuple和pair都是用于存储多个值的工具。tuple可以存储任意数量的元素,而pair只能存储两个元素。既然tuple的功能更强大,为什么C标准库仍然保留了pair呢?本文将从多个角度探讨这个问题。 1. 历史兼容性 pair在C标准库中比tu…...
Open WebUI项目源码学习记录(从0开始基于纯CPU环境部署一个网页Chat服务)
感谢您点开这篇文章:D,鼠鼠我是一个代码小白,下文是学习开源项目Open WebUI过程中的一点笔记记录,希望能帮助到你~ 本人菜鸟,持续成长,能力不足有疏漏的地方欢迎一起探讨指正,比心心~…...
什么是Grok-3?技术特点,场景,潜在问题与挑战
Grok-3 的技术特点与优势 1. 超大算力与训练规模 算力投入:Grok-3 使用了 20 万块英伟达 H100 GPU,分两个阶段训练(第一阶段 10 万 GPU 训练 144 天,第二阶段 20 万 GPU 训练 92 天),总计算量是前代 Grok-2 的 10 倍。这种规模远超同期其他项目(如印度的 1.8 万 GPU 公…...
容器docker k8s相关的问题汇总及排错
1.明确问题 2.排查方向 2.1、 docker方面 docker logs -f 容器ID docker的网络配置问题。 2.2、 k8s方面 node组件问题 pod的问题(方式kubectl describe po pod的名称 -n 命名空间 && kubectl logs -f pod的名称 -n 命名空间) 调度的问题&#x…...
【Docker】百度网盘:基于VNC的Web访问及后台下载
本教程通过 Docker Compose 部署百度网盘的 VNC 版本,实现24小时不间断下载、双模式访问、数据持久化、自动重启和安全加密控制等核心功能。 目录结构规划 建议使用以下目录结构(可根据实际情况调整): ~/baidunetdisk/├── d…...
JWT 令牌
目录 一、JWT 1、什么是JWT 2、JWT的组成 3、JJWT签发与验证token 1、创建token 2、解析token 3、设置过期时间 4、自定义claims 前言: 在现代Web应用和微服务架构中,用户身份验证和信息安全传输是核心问题。JSON Web Token(J…...
鼎捷PLM深度集成DeepSeek,领跑智能研发新赛道
新年伊始,DeepSeek以其卓越的性能、高性价比和开源优势,掀起一股AI技术应用热潮,重塑各行各业的知识管理、知识应用模式。对制造业来说,首当其冲的就是研发管理变革,这也引发了企业的深度思考:在工业领域的…...
设计模式之适配模式是什么?以及在Spring AOP中的拦截器链的使用源码解析。
前言 本文涉及到适配模式的基本用法,以及在Spring AOP中如何使用,首先需要了解适配模式的工作原理,然后结合Spring AOP的具体实现来详细详细解析源码。 首先,适配模式,也就是Adapter Pattern,属于结构型设计…...
挖掘图片的秘密:如何用piexif提取和修改Exif数据
Exif(Exchangeable Image File Format)数据是一个广泛用于数字图像(尤其是JPEG和TIFF格式)中的元数据格式。它包含了关于图像的各种信息,包括拍摄设备的类型、拍摄时间、光圈、曝光时间、GPS定位信息等。Exif数据使得用…...
javaSE学习笔记22-线程(thread)-线程通信、线程池
线程通信 应用场景:生产者和消费者问题 假设仓库中只能存放一件产品,生产者将生产出来的产品放入仓库,消费者将仓库中产品取走消费 如果仓库中没有产品,则生产者将产品放入仓库,否则停止生产并等待,…...
VMware新建虚拟机
看看自己的电脑是什么内核,有几个处理器 再分配给虚拟机 镜像文件需要自己安装下载地方https://mirrors.aliyun.com/centos/?spma2c6h.13651104.d-2001.8.3fb1320cuI1jeS 然后就出现了 然后开启虚拟机,等待 等待之后如下,选择语言 等待一段时…...
Windows 11运行《拳皇98UM》等老游戏闪退解决方案
问题:游戏可以进入选项菜单,但只要进行键盘操作就会卡死并闪退。 问题分析:该游戏兼容DirectX 9,但可能不向上兼容。而Windows 11默认安装的是DirectX 12,并不兼容低版本的DirectX,这可能导致该游戏或其他…...
使用iOS个人声音与SoVITS训练个人AI语音(10分钟快速上手)
使用iOS个人声音与SoVITS训练个人AI语音(10分钟快速上手) 序言:最近在抖音上频繁看到曼波唱歌的视频和各种AI语音的搞笑短片,加上年后新购置的M2硬盘终于提供了足够的存储空间,让我有机会深入研究AI语音训练。24年年初…...
【JavaEE进阶】Spring MVC(3)
欢迎关注个人主页:逸狼 创造不易,可以点点赞吗 如有错误,欢迎指出~ 返回响应 返回静态页面 //RestController Controller RequestMapping("/response") public class ResponseController {RequestMapping("/returnHtmlPage&…...
火语言RPA--Excel读取内容
【组件功能】:读取Excel内指定位置的内容或读取整篇Sheet页内容 配置预览 配置说明 读取位置 单元格:读取指定单元格中的内容。 行:读取指定行内容。 列:读取指定列内容。 区域:读取指定区域内容。 整篇sheet页&…...
