Let’s Make C++ Great Again——set与vector
文章目录
- set
- 常用的set方法:
- set实现去重的例子:
- 自定义比较函数的例子,按照字符串长度从小到大排序:
- 使用set容器求两个集合的交集的例子:
- vector
- 创建vector对象
- 插入和删除元素
- 获取vector的大小和容量
- 检查vector是否为空
- 访问vector的首尾元素
- 修改vector的大小
- 清空vector
- 交换vector
- vector的迭代器
- vector的性能
- 自定义vector元素类型
- 使用emplace_back()方法
- 使用reserve()方法
- 使用std::move()函数
- vector在算法模拟题中
- 存储动态数组
- 模拟栈操作
- 实现动态规划
set
在C++中,set是一个标准的关联容器,它使用红黑树数据结构来存储元素,并保证元素按照一定的顺序排列。set中的元素是唯一的,不能重复。
set容器提供了一系列方法,包括插入元素、删除元素、查找元素、遍历元素等,可以方便地实现对元素的操作。
常用的set方法:
insert(val):将元素val插入到set中。erase(val):从set中删除值为val的元素。find(val):在set中查找值为val的元素,并返回指向该元素的迭代器。size():返回set中元素的个数。begin():返回指向set中第一个元素的迭代器。end():返回指向set中最后一个元素之后位置的迭代器,通常用于遍历set中的元素。empty():判断set是否为空,如果为空则返回true,否则返回false。clear():清空set中的所有元素。count(val):返回set中值为val的元素的个数,因为set中元素不重复,所以返回值只能是0或1。lower_bound(val):返回一个指向第一个不小于val的元素的迭代器。upper_bound(val):返回一个指向第一个大于val的元素的迭代器。equal_range(val):返回一个迭代器对,其中第一个迭代器指向set中第一个等于val的元素,第二个迭代器指向set中第一个大于val的元素。
set实现去重的例子:
#include <iostream>
#include <set>using namespace std;int main() {set<int> myset;myset.insert(10);myset.insert(20);myset.insert(30);myset.insert(20);myset.insert(40);cout << "Set contains " << myset.size() << " elements: ";for (auto it = myset.begin(); it != myset.end(); it++) {cout << *it << " ";}cout << endl;return 0;
}
Set contains 4 elements: 10 20 30 40
set还支持自定义比较函数,可以根据不同的需求来定义元素之间的比较方式,例如按照字符串长度进行排序等。
自定义比较函数的例子,按照字符串长度从小到大排序:
#include <iostream>
#include <set>
#include <string>using namespace std;struct cmp {bool operator() (const string& a, const string& b) const {return a.length() < b.length();}
};int main() {set<string, cmp> myset;myset.insert("apple");myset.insert("banana");myset.insert("pear");myset.insert("orange");cout << "Set contains " << myset.size() << " elements: ";for (auto it = myset.begin(); it != myset.end(); it++) {cout << *it << " ";}cout << endl;return 0;
}
Set contains 4 elements: pear apple banana orange
可以看到,程序根据字符串长度从小到大排序了元素。
总之,set是一个非常有用的容器,可以方便地实现对元素的操作,并且保证元素无重复。在实际的编程中,我们可以根据不同的需求来灵活地使用set容器。
在算法模拟题中,set容器通常用于实现集合的概念,即存储一些元素,同时保证元素无重复。在模拟一些实际场景时,例如计算两个集合的交集、并集等操作时,set容器可以很方便地实现这些操作。
使用set容器求两个集合的交集的例子:
#include <iostream>
#include <set>using namespace std;int main() {set<int> A = {1, 2, 3, 4, 5};set<int> B = {2, 4, 6, 8};set<int> C;for (auto it = A.begin(); it != A.end(); it++) {if (B.count(*it)) {C.insert(*it);}}cout << "A: ";for (auto it = A.begin(); it != A.end(); it++) {cout << *it << " ";}cout << endl;cout << "B: ";for (auto it = B.begin(); it != B.end(); it++) {cout << *it << " ";}cout << endl;cout << "C: ";for (auto it = C.begin(); it != C.end(); it++) {cout << *it << " ";}cout << endl;return 0;
}
A: 1 2 3 4 5
B: 2 4 6 8
C: 2 4
可以看到,程序使用set容器实现了对两个集合求交集的操作。
除了求交集、并集等操作外,set容器还可以用于对元素进行排序、去重等操作。在进行算法模拟题时,我们可以根据实际需要灵活地使用set容器,以实现对元素的操作和处理。
vector
vector是C++标准库中的一个容器类,用于存储元素的动态数组,可以实现自动扩容、快速随机访问等功能。下面介绍一些vector的基本用法。
创建vector对象
可以通过以下方式来创建一个vector对象:
#include <vector>using namespace std;vector<int> v; // 创建一个空的vector对象
可以在创建时指定初始大小和初始值:
vector<int> v1(10); // 创建一个大小为10的vector对象,每个元素的值为0
vector<int> v2(10, 1); // 创建一个大小为10的vector对象,每个元素的值为1
vector<int> v3{1, 2, 3}; // 创建一个包含3个元素的vector对象,值分别为1、2、3
vector<int> v4 = {4, 5, 6}; // 与v3等价
插入和删除元素
可以使用push_back()方法在vector的末尾插入一个元素:
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
也可以使用insert()方法在指定位置插入一个元素:
vector<int> v{1, 2, 3};
v.insert(v.begin() + 1, 4); // 在下标为1的位置插入元素4
可以使用pop_back()方法删除vector末尾的一个元素:
vector<int> v{1, 2, 3};
v.pop_back();
也可以使用erase()方法删除指定位置的一个或多个元素:
vector<int> v{1, 2, 3};
v.erase(v.begin() + 1); // 删除下标为1的元素
v.erase(v.begin() + 1, v.end() - 1); // 删除下标为1到末尾前一个位置的元素
访问元素
可以使用下标运算符[]或at()方法来访问vector中的元素,下标从0开始:
vector<int> v{1, 2, 3};
int x = v[0]; // x的值为1
int y = v.at(1); // y的值为2
也可以使用迭代器来访问vector中的元素:
vector<int> v{1, 2, 3};
for (auto it = v.begin(); it != v.end(); it++) {cout << *it << " "; // 输出1 2 3
}
获取vector的大小和容量
可以使用size()方法获取vector中元素的个数:
vector<int> v{1, 2, 3};
int n = v.size(); // n的值为3
可以使用capacity()方法获取vector中能够容纳的元素个数:
vector<int> v{1, 2, 3};
int m = v.capacity(); // m的值为3
需要注意的是,vector的实际大小和容量可能不一致,因为vector会动态调整大小和容量以适应元素的增减。
检查vector是否为空
可以使用empty()方法检查vector是否为空:
vector<int> v{1, 2, 3};
if (v.empty()) {cout << "vector is empty" << endl;
} else {cout << "vector is not empty" << endl;
}
访问vector的首尾元素
可以使用front()方法和back()方法分别访问vector的第一个和最后一个元素:
vector<int> v{1, 2, 3};
int x = v.front(); // x的值为1
int y = v.back(); // y的值为3
修改vector的大小
可以使用resize()方法修改vector的大小,如果新的大小比原来的大小小,则会删除多余的元素,如果新的大小比原来的大小大,则会添加默认值的元素:
vector<int> v{1, 2, 3};
v.resize(5); // v的大小变为5,多余的元素的值为0
v.resize(2); // v的大小变为2,多余的元素被删除
清空vector
可以使用clear()方法清空vector中的所有元素:
vector<int> v{1, 2, 3};
v.clear(); // v中的元素被清空
交换vector
可以使用swap()方法交换两个vector对象:
vector<int> v1{1, 2, 3};
vector<int> v2{4, 5, 6};
v1.swap(v2); // v1和v2中的元素被交换
需要注意的是,使用swap()方法可以在不需要额外的内存空间的情况下交换两个vector对象,因此可以有效避免内存泄漏的问题。
vector的迭代器
vector的迭代器可以用来遍历vector中的元素,可以使用begin()方法和end()方法分别获取指向第一个元素和最后一个元素之后位置的迭代器:
vector<int> v{1, 2, 3};
for (auto it = v.begin(); it != v.end(); it++) {cout << *it << " "; // 输出1 2 3
}
需要注意的是,vector的迭代器不是指针类型,但是可以通过解引用*运算符来访问迭代器指向的元素。
vector的性能
vector的性能在大多数情况下都非常好,可以达到常数时间复杂度。但是,由于vector的动态扩容需要重新分配内存并复制元素,因此在频繁增加元素的情况下,可能会导致性能下降。此外,vector的内存分配可能不是连续的,这也可能会影响性能。
自定义vector元素类型
vector可以存储任何类型的元素,包括内置类型、自定义类型、指针等。如果要存储自定义类型的元素,需要定义一个适当的构造函数和析构函数。
例如,假设我们有一个自定义类型Person,其中包含姓名和年龄两个字段:
#include <string>using namespace std;class Person {
public:Person(const string& name, int age) : name_(name), age_(age) {}string name() const { return name_; }int age() const { return age_; }
private:string name_;int age_;
};
然后可以定义一个vector来存储Person类型的元素:
vector<Person> v;
v.push_back(Person("Alice", 20));
v.push_back(Person("Bob", 30));
需要注意的是,如果Person类中包含指针等动态分配内存的成员变量,需要自定义拷贝构造函数和赋值运算符,以确保正确地复制和释放内存。
使用emplace_back()方法
emplace_back()方法可以在vector的末尾直接构造新的元素,而不是先创建一个临时对象再复制到vector中,从而可以避免不必要的拷贝操作,提高性能。
例如,假设我们有一个vector来存储Person类型的元素,可以使用emplace_back()方法来添加新的元素:
vector<Person> v;
v.emplace_back("Alice", 20);
v.emplace_back("Bob", 30);
需要注意的是,emplace_back()方法的参数应该与元素类型的构造函数所需的参数匹配。
使用reserve()方法
reserve()方法可以预先分配一定数量的内存空间,以避免在添加大量元素时反复进行动态内存分配和复制操作,从而提高性能。
例如,假设我们需要存储一百万个int类型的元素,可以使用reserve()方法预先分配内存空间:
vector<int> v;
v.reserve(1000000);
for (int i = 0; i < 1000000; i++) {v.push_back(i);
}
需要注意的是,reserve()方法只会预先分配内存空间,而不会改变vector的大小,因此需要在添加元素之前使用reserve()方法。
使用std::move()函数
std::move()函数可以将一个对象的所有权转移给另一个对象,从而避免不必要的拷贝操作,提高性能。
例如,假设我们有一个vector,需要将其中的元素移动到另一个vector中:
vector<Person> v1;
vector<Person> v2;
// 添加元素到v1中
v2.reserve(v1.size());
for (auto& p : v1) {v2.push_back(std::move(p));
}
v1.clear(); // 清空v1
需要注意的是,使用std::move()函数需要确保被移动的对象不再使用,否则可能会出现未定义的行为。
总之,vector是一个非常实用的容器类,在处理动态数组的问题时非常方便。需要注意的是,在使用vector时需要了解其高级特性,并结合具体的应用场景进行优化,以提高性能和减少内存开销。
vector在算法模拟题中
在算法模拟题中,vector是一个非常实用的容器类,可以方便地处理动态数组的问题。以下是一些常见的算法模拟题中使用vector的场景:
存储动态数组
在模拟数组操作时,可以使用vector来存储动态数组。例如,假设需要实现一个队列,可以使用vector来存储队列中的元素:
vector<int> q; // 定义一个vector来存储队列中的元素
q.push_back(1); // 添加元素到队列末尾
q.push_back(2);
q.push_back(3);
int x = q.front(); // 获取队列头部元素
q.erase(q.begin()); // 删除队列头部元素
模拟栈操作
在模拟栈操作时,也可以使用vector来存储栈中的元素。例如,假设需要实现一个栈,可以使用vector来存储栈中的元素:
vector<int> s; // 定义一个vector来存储栈中的元素
s.push_back(1); // 添加元素到栈顶
s.push_back(2);
s.push_back(3);
int x = s.back(); // 获取栈顶元素
s.pop_back(); // 删除栈顶元素
实现动态规划
在动态规划问题中,通常需要定义一个二维数组来存储状态。可以使用vector来实现这个二维数组,并使用resize()方法来动态调整数组大小。例如,假设需要实现一个最长公共子序列问题的动态规划算法,可以使用vector来存储状态:
string s1 = "ABCBDAB";
string s2 = "BDCABA";
vector<vector<int>> dp(s1.size() + 1, vector<int>(s2.size() + 1));
for (int i = 1; i <= s1.size(); i++) {for (int j = 1; j <= s2.size(); j++) {if (s1[i - 1] == s2[j - 1]) {dp[i][j] = dp[i - 1][j - 1] + 1;} else {dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);}}
}
int ans = dp[s1.size()][s2.size()]; // 最长公共子序列的长度
需要注意的是,使用vector来实现二维数组时,应该将数组定义为vector<vector>类型,并使用resize()方法来动态调整数组大小。
总之,在算法模拟题中,vector是一个非常实用的容器类,可以方便地处理动态数组的问题,并且可以根据具体的应用场景进行优化,以提高性能和减少内存开销。
相关文章:
Let’s Make C++ Great Again——set与vector
文章目录 set常用的set方法:set实现去重的例子:自定义比较函数的例子,按照字符串长度从小到大排序:使用set容器求两个集合的交集的例子: vector创建vector对象插入和删除元素获取vector的大小和容量检查vector是否为空…...
Nginx+Tomcat负载均衡、动静分离
一.Nginx负载均衡实现原理 Nginx实现负载均衡是通过反向代理实现 1、 反向代理原理 2、反向代理的概念 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服…...
SpringCloud入门实战(七)-Hystrix服务熔断
📝 学技术、更要掌握学习的方法,一起学习,让进步发生 👩🏻 作者:一只IT攻城狮 。 💐学习建议:1、养成习惯,学习java的任何一个技术,都可以先去官网先看看&…...
百度平地起“雷”,突然爆出的QPS数据意味着什么?
鲁迅先生1923年在北师大发表了著名的演讲《娜拉走后怎样》,其中的提问与思考方式振聋发聩,直到今天也依旧有效。面对很多产业现象、技术趋势,我们也不妨多问几个“之后怎样”。 比如说,自ChatGPT爆火之后,中国各个互联…...
电子模块|外控集成 LED 光源 WS2812模块---硬件介绍和stm32驱动
电子模块|外控集成 LED 光源 WS2812模块 模块简介模块特点机械尺寸单线归零码通讯方式24bit 数据结构 stm32 驱动 模块简介 WS2812是一个集控制电路与发光电路于一体的智能外控LED光源。其外型与一个5050LED灯珠相同,每个元件即为一个像素点。像素点内部包含了智能…...
Jenkins+Python自动化测试持续集成详细教程(全网独家)
目录 一、前言 二、环境准备 三、创建Jenkins Job 四、编写Python自动化测试脚本 五、测试报告生成与展示 六、持续集成流程优化 七、实战演练 八、常见问题及解决方案 九、结论 一、前言 Jenkins是目前最为流行的CI/CD工具之一,它可以支持多种语言和技术…...
运维监控工具PIGOSS BSM扩展指标介绍
PIGOSS BSM运维监控工具,除系统自带指标外,还支持添加SNMP扩展指标、脚本扩展指标、JMX扩展指标、自定义JDBC指标等,今天本文将介绍如何添加SNMP扩展指标和脚本扩展指标。 添加SNMP扩展指标 前提:需要知道指标的oid 例子ÿ…...
一些前端问题2
1.业务场景中需要嵌入公司其他行业线的页面,这种不使用 iframe 该怎么办? 答:理论上应该让他们给你做个组件出来,但是如果实在没别的办法,就使用 iframe 吧。 2.jquery ajax 同步请求的原理是? 目前用 axios 库&…...
Moviepy模块之视频添加图片水印
文章目录 前言视频添加图片水印1.引入库2.加载视频文件3.加载水印图片4.缩放水印图片大小5.设置水印的位置5.1 相对于视频的左上角5.2 相对于视频的左下角5.3 相对于视频的右上角5.4 相对于视频的右下角5.5 相对于视频的左中位置5.6 相对于视频的正中位置5.7 相对于视频的右中位…...
day35—编程题
文章目录 1.第一题1.1题目1.2思路1.3解题 2.第二题2.1题目2.2思路2.3解题 1.第一题 1.1题目 描述: 今年公司年会的奖品特别给力,但获奖的规矩却很奇葩: 首先,所有人员都将一张写有自己名字的字条放入抽奖箱中;待所有…...
Linux安装Nginx
前言 提示:这里可以添加本文要记录的大概内容: Linux安装Nginx的详细步骤。 一、安装Nginx的相关依赖 1、安装gcc,PCRE pcre-devel,zlib,OpenSSL, 提示:安装 nginx 需要先将官网下载的源码进行编译,编译依赖 gcc 环境。 PCRE(…...
Qt 项目Mingw编译器转换为VS编译器时的错误及解决办法
错误 在mingw生成的项目,转换为VS编译器时通常会报些以下错误(C4819警告,C2001错误,C2143错误) 原因及解决方式 这一般是由于字符编码引起的,在源代码文件中包含了中文字符导致的。Qt Creator 生成的代码文…...
大学生用什么蓝牙耳机好?2023好用的蓝牙耳机推荐
近几年,蓝牙耳机市场不断扩大,逐渐取代有线耳机成为最受人欢迎的数码产品之一。作为蓝牙耳机主要受众群的大学生,用什么蓝牙耳机比较好呢?下面,我来给大家推荐几款便宜好用的蓝牙耳机,一起来看看吧。 一、…...
【好题】好题分享
1001-四舍五入_牛客竞赛语法入门班数组模拟、枚举、贪心习题 (nowcoder.com) 题目描述 四舍五入是个好东西。比如你只考了45分,四舍五入后你是50分再四舍五入你就是满分啦!qdgg刚考完拓扑。成绩十分不理想。但老师觉得他每天都很认真的听课很不容易。于是…...
three.js 怎么在自动缩放的时候添加动画效果
要在自动缩放的时候添加动画效果可以使用three.js中的Tween.js库。Tween.js提供了一种简单的方式来创建和管理动画,它可以让开发者通过简单的API来控制对象的属性变化,从而实现动画效果。 以下是一个使用Tween.js实现模型缩放动画的示例: 加…...
考虑梯水电站群的水火电节能调度(Python代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
CF914G Sum the Fibonacci
CF914G Sum the Fibonacci 洛谷Sum the Fibonacci 题目大意 给你一个长度为 n n n的数组 s s s,定义五元组 ( a , b , c , d , e ) (a,b,c,d,e) (a,b,c,d,e)是合法的当且仅当: 1 ≤ a , b , c , d , e ≤ n 1\leq a,b,c,d,e\leq n 1≤a,b,c,d,e≤n ( …...
Shell基础入门实战
写在前面 好久没在项目内做自动化了,主要是现阶段在项目内做自动化收益不大,最近开发做batch run的正好缺人,我看了一下代码,就是通过代码读取jar包和远程服务器连接,然后通过shell脚本,向数据库插入数据&a…...
如何进行微服务的技术选型?
本文首发自「慕课网」,想了解更多IT干货内容,程序员圈内热闻,欢迎关注"慕课网"! 作者:陈于吉吉|慕课网讲师 随着这几年微服务的火爆,在平时的工作或者技术交流中,我们总能听到哪家公…...
Vue电商项目--应用开发详解
vue-cli脚手架初始化项目 首先,页面上新建一个文件夹。然后打开命令端口 vue create app 选择Default ([Vue 2] babel, eslint) 然后把项目拖拽到vscode中。项目目录看一下 脚手架项目的目录 node_modules:放置项目依赖的地方 public:一般放置一些共用的静态资源&a…...
基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
LOOI机器人的技术实现解析:从手势识别到边缘检测
LOOI机器人作为一款创新的AI硬件产品,通过将智能手机转变为具有情感交互能力的桌面机器人,展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家,我将全面解析LOOI的技术实现架构,特别是其手势识别、物体识别和环境…...
永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器
一、原理介绍 传统滑模观测器采用如下结构: 传统SMO中LPF会带来相位延迟和幅值衰减,并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF),可以去除高次谐波,并且不用相位补偿就可以获得一个误差较小的转子位…...
git: early EOF
macOS报错: Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/.git/ remote: Enumerating objects: 2691797, done. remote: Counting objects: 100% (1760/1760), done. remote: Compressing objects: 100% (636/636…...
深度解析:etcd 在 Milvus 向量数据库中的关键作用
目录 🚀 深度解析:etcd 在 Milvus 向量数据库中的关键作用 💡 什么是 etcd? 🧠 Milvus 架构简介 📦 etcd 在 Milvus 中的核心作用 🔧 实际工作流程示意 ⚠️ 如果 etcd 出现问题会怎样&am…...
【题解-洛谷】P10480 可达性统计
题目:P10480 可达性统计 题目描述 给定一张 N N N 个点 M M M 条边的有向无环图,分别统计从每个点出发能够到达的点的数量。 输入格式 第一行两个整数 N , M N,M N,M,接下来 M M M 行每行两个整数 x , y x,y x,y,表示从 …...
