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…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...
