vetor(数组)
迭代器
迭代器就相当于STL中的指针,按照定义方式,可以分为下面四类:
- 正向迭代器:容器类名
::iterator
迭代器名; begin(); end(); - 常正向迭代器:容器类名
::const_iterator
迭代器名; cbegin(); cend(); - 反向迭代器:容器类名
::reverse_iterator
迭代器名; rbegin(); rend(); - 常反向迭代器:容器类名
::const_reverse_iterator
迭代器名; crbegin(); crend();
迭代器用法示例:
通过迭代器可以读取它指向的元素,*迭代器名就表示迭代器指向的元素。
- 对正向迭代器进行++操作时,迭代器会指向容器中的后一个元素;
- 反向迭代器进行++操作时,迭代器会指向容器中的前一个元素;
#include<vector>
#include<iostream>
using namespace std;
int main(){
vector<int> v; //v是存放int类型变量的可变长数组,开始时没有元素
for(int n = 0; n < 5; n++)
v.push_back(n); //push_back函数在vector容器尾部添加一个元素
//定义正向迭代器
vector<int>::itertor i;
for(i = v.begin(); i != v.end(); ++i){ //用迭代器遍历容器
cout << *i << " "; //*i 就是迭代器i指向的元素
*i *= 2; //每个元素变为原来的2倍
}
cout << endl;
//定义常正向迭代器
for(vector<int>::const_itartor i = v.cbegin(); i != v.cend(); ++i)
cout << *i << " ";
//定义反向迭代器
for(vector<int>::reverse_itartor i = v.rbegin(); i != v.rend(); ++i)
cout << *i << " ";
//定义反向迭代器
for(vector<int>::const_reverse_itartor i = v.crbegin(); i != v.crend(); ++i)
cout << *i << " ";
return 0;
}
程序输出结果:
0 1 2 3 4
0 2 4 6 8
8 6 4 2 0
8 6 4 8 0
第12行和第23行相当如下:
CDemo CDemo::operator++ ()
{ //前置++
++n;
return *this;
}
CDemo CDemo::operator ++(int k)
{ //后置++
CDemo tmp(*this); //记录修改前的对象
n++;
return tmp; //返回修改前的对象
}
按照功能分类:
容器 | 迭代器功能 |
---|---|
vector | 随机访问 |
deque | 随机访问 |
list | 双向 |
set/multiset | 双向 |
map/multimap | 双向 |
stack | 不支持迭代器 |
queue | 不支持迭代器 |
priority_queue | 不支持迭代器 |
例如,vector的迭代器是随机迭代器,因此遍历vector容器有以下几种做法。【实例】遍历vector容器。
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int> v(100); //v被初始化成有100个元素
for(int i = 0; i < v.size(); i++) //size返回元素个数
cout << v[i]; //像普通数组一样使用vector容器
vector<int>::iterator i;
//用于双向迭代器,双向迭代器不支持 “<”进行比较
for(i = v.begin(); i != end(); i++) //用!=比较两个迭代器
cout << *i ;
//用于单向迭代器
for(i = v.begin(); i < v.end(); i++) //用 < 比较两个迭代器
cout << *i;
i = v.begin();
while(i < v.end()){//间隔一个输出
cout << *i;
i += 2; //随机访问迭代器支持 “+= 整数” 的操作
}
}
迭代器的辅助函数
STL中有用于操作迭代器的三个函数模板,它们是:
advance(p, n); //使迭代器p向前或向后移动元素
distance(p, q); //计算两个迭代器之间的距离,即迭代器p经过多少次++操作后和迭代器q相等。如果调用p时已经指向q的后面,则这个函数会陷入死循环。
iter_swap(p, q); //用于交换两个迭代器p、q指向的值
实际函数操作如下:
#include<list>
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int a[5] = {1, 2, 3, 4, 5};
list<int> lst(a, a + 5);
list<int>::iterator p = list.begin();
advance(p, 2); //p向后移动两个元素,指向3
cout << "1)" << *p << endl; //输出1)3
advance(p, -1); //p向前移动一个元素,指向2
cout << "2)" << *p << endl; //输出2)2
list<int>::iterator q = list.end();
q--; //q指向 5
cout << "3)" << distance(p, q) << endl; //输出 3)3
iter_swap(p, q); //交换 2 和 5
cout << "4)";
for(p = lst.begin(); p != lst.end(); p++)
cout << *p << ednl;
return 0;
}
程序输出结果:
1)3
2)2
3)3
4)1 5 3 4 2
vetor的定义和特性
在c++中,vector是一个动态数组容器,可以存储一系列相同类型的元素。它是标准库==== 中定义的模板类。
vetor的定义和结构非常简单,它由以下几个重要的部分组成:
模板类声明: vetor是一个模板类,因此在使用之前需要包含头文件.声明一个vetor对象的通用语法如下:
vetor<T> vec; //这里的T是要存储在vector中的元素类型
//T可以为int、char、double......
容器大小: vector是一个动态数组,可以根据需要自动调整大小。它会根据元素的数量动态分配内存空间。
元素访问: 可以通过索引来访问vector中的元素。索引从0开始,最后一个元素的索引是size() - 1。可以使用[ ]运算符或at()函数来访问元素
元素添加和删除: 可以使用push_back()函数在vector中元素的数量,使用empty()函数检查vector是否为空。还可以使用resize()函数调整vector的大小
迭代器: vector提供了迭代器,可以用于遍历容器中的元素,可以使用begin()函数获取一个元素的迭代器,使用end() 函数获取指向最后一个元素之后位置的迭代器。
vector的常用函数
push_back(): 将元素添加到vector的末尾
void push_back(const T& value);
pop_back(): 删除vector末尾的元素
void pop_back();//一定要保证vector非空
begin() 和 end(): 返回指向vector第一个元素和最后一个元素之后位置的迭代器
例子:
vector<int> vec = {10, 20, 30};
for(auto it = vec.begin(); it != vec.end(); ++it){
cout << *it << " ";
}
vector排序去重
排序: 要对vector进行排序,可以使用标准库中的sort函数,该函数位于头文件中。
#include<algorithm>
vector<T> vec = {. . .};
//这里T是vector 中元素的类型
sort(vec.begin(),vec.end());
//sort函数接受两个迭代器参数,表示要排序的范围
//vec.begin()返回指向vector第一个元素的迭代器
//vec.end()返回指向最后一个元素之后位置的迭代器
示例
#include<iostream>
#include<vector>
#include<algorlthm>
int main(){
vector<int> vec = {5, 2, 8, 1, 9};
sort(vec.begin(),vec.end());
for(const auto& num : vec){
cout << num << " ";
}
return 0;
}
输出
1 2 5 8 9 |
---|
去重: 要去除vector中的重复元素,可以使用unique函数。该函数位于头文件中。
#include<algorithm>
vector<T> vec = { . . .};
sort(vec.begin(),vec.end());
auto last = =unique(vec.begin(),vec.end());
vec.erase(last,vec.end());
首先,需要对vector进行排序,以便相同的元素相邻。然后,,unique函数将重复的元素移动到vector的末尾,并返回一个指向重复的迭代器。最后,可以使用vec.erase函数将重复元素从vector中删除
示例:
#include<iostream>
#include<vector>
#include<algorlthm>
int main(){
vector<int> vec = {2, 1, 3, 2, 4, 1, 5, 4};
sort(vec.begin(),vec.end());
auto last = =unique(vec.begin(),vec.end());
vec.erase(last,vec.end());
for(const auto& num : vec){
cout << num << " ";
}
return 0;
}
//注意vector中的重复元素被去除,只保留了不重复的元素。
输出:
1 2 3 4 5 |
---|
queue(队列)
queue队列
queue是一种先进后出(FIFO)的数据结构
queue提供了一组函数来操作和访问元素,但它的功能相对简单
queue的定义和结构如下:
template<class T, class Container = deque<T>>
class queue;
//T:表示存储在queue中的元素的类型
//Container:表示底层容器的类型,默认为deque。也可以使用其他容器类型,如list
queue的内部实现使用了底层容器来存储元素,并且只能通过特定的函数来访问和操作元素,以下是一些queue的常用函数:
#include<queue> //queue容器的头文件
queue<int> q; //声明
struct node {int x, y, z;};
queue<node> qq; //声明一个结构体类型的队列容器
q.push(111); //将111插入队尾 O(1)
q.pop(); //将队头元素删除 O(1)
int x = q.front(); //返回队头元素 O(1)
int y = q.back(); //返回队尾元素 O(1)
priority_queue按照元素从大到小排序
tempplate<class T, class Container = vector<T>,
class Compare = less<typename //比较函数
Container::value_type>>
class priority_queue;
//T:表示存储在queue中的元素的类型
//Container:表示底层容器的类型,默认为deque。也可以使用其他容器类型,如deque
//Compare:表示元素之间的比较函数对象的类型,默认为less,即按照元素的值进行比较
priority_queue的内部实现使用了底层容器来存储元素,并且只能通过特定的函数来访问和操作元素。以下是一些priority_queue的常用函数:
函数 | 描述 | 时间复杂度 |
---|---|---|
push(x) | 将元素x插入到优先队列中 | O(logN) |
pop() | 弹出有限队列中的顶部元素 | O(logN) |
top() | 返回优先队列中的顶部元素 | O(1) |
empty() | 检查优先队列是否为空 | O(1) |
size() | 返回优先队列中元素的个数 | O(1) |
几种优先队列修改比较函数的方法
struct Compare{
bool operator()(int a, int b){
//自定义的比较函数,按照逆序排列
return a > b;
}
}
int main(){
priority_queue<int, vector<int>,Compare> pq;
auto compare = [](int a, int b){
//自定义的比较函数,按照逆序排序
return a > b;
}
priority_queue<int, vector<int>,Compare> pq(compare);
}
如果优先队列中的元素类型比较简单,可以直接使用
greater来修改比较方法.
priority_queue<int, vector, greater> pq;
greater函数对象定义在头文件中
deque双端队列
deque(双端队列)是一个容器,它允许在两端进行高效的插入和删除操作。
template<class T, class Allocator = allocator<T>
class deque;
//T表示存储在deque中的元素的类型
//Allocator:表示用于分配内存的分配器类型,默认为allocator
函数 | 描述 | 时间复杂度 |
---|---|---|
push_back(x) | 在尾部插入元素x | 平摊O(1) |
push_front(x) | 在头部插入元素x | 平摊O(1) |
pop_back() | 弹出尾部元素 | 平摊O(1) |
pop_front() | 弹出头部元素 | 平摊O(1) |
front() | 返回头部元素 | O(1) |
back() | 返回尾部元素 | O(1) |
empty() | 检查deque是否为空 | O(1) |
size() | 返回deque中元素的个数 | O(1) |
clear() | 清空deque中所有的元素 | O(N) |
insert(pos,x) | 在指定位置pos插入元素 | 平摊O(N) |
---|---|---|
erase(pos) | 移除指定位置pos处的元素 | 平摊O(N) |
erase(first,last) | 移除(first,last)范围内的元素 | 平摊O(N) |
set
set集合
set 是一种容器,用于存储一组唯一的元素,并按照一定的排序规则进行排序。set中的元素是按照升序排序的,默认情况下,它使用元素的比较运算符(<)来进行排序。
set的定义结构如下:
template<class key, class Compare = less<key>,
class Allocator = allocator<key>>
class set;
- key: 表示存储在set中的元素的类型。
- Compare: 表示元素之间的比较函数对象的类型,默认为less,即按照元素的值进行比较。
- Allcoator: 表示用于分配内存的分配器类型,默认为allocator.
set的内部实现使用了红黑树(一种自平衡的二叉搜索树)来存储元素,并爆出元素的有序性,这使得在set中插入、删除和查找元素的时间复杂度都是对数时间,即O(log n).
set中的元素是唯一的,即不允许重复的元素存在,当插入一个重复的元素时,set会自动忽略该元素。
set函数
s.insert(key); //向set中插入一个元素key。
s.erase(key); //从set中移除指定的元素key。
s.find(key); //查找set中是否存在指定的元素key,如果存在则返回指向该元素的迭代器,否则返回set::end()。
s.lower_bound(key); //返回指向第一个不小于给定键值key的元素的迭代器。
s.upper_bound(key); //返回指向第一个大于给定键值key的元素的迭代器。
s.equal_range(); //返回一个返回,其中包含所有给定的元素
s.size(); //返回集合中元素的数量
s.empty(); //检查集合是否为空
s.clear(); //清空set中的所有元素。
s.begin(); //指向集合中最小元素的迭代器
s.end(); //指向集合中最大元素的下一个位置的迭代器
s.rebegin(); //返回指向集合末尾位置的逆向迭代器
s.rend(); //返回指向集合起始位置的逆向迭代器
s.swap(); //交换两个集合
s.count(key); //返回set中与指定元素key相等的元素的个数,由于set中不允许有重复的元素,因此返回值只能是0或1。
修改set比较方法的常见手段,后面的multiset类似
#include<iostream>
#include<set>
using namespace std;
int main(){
set<int,greater<int>> mySet;
mySet.insert(25);
mySet.insert(17);
mySet.insert(39);
mySet.insert(42);
for(const auto& elem : mySet){
cout << elem << " ";
}
cout << endl;
return 0;
}
#include<iostream>
#include<set>
using namespace std;
struct MyCompare{
bool operator()(const int& a, const int& b) const{
//自定义比较逻辑
return a > b;//改为逆序
}
};
int main(){
set<int, MyCompare> mySet; //mYCompare是仿函数
mySet.inster(25);
mySet.inster(17);
mySet.inster(39);
mySet.inster(42);
for(const auto& elem : mySet){
cout << elem << " ";
}
cout << endl;
return 0;
}
multiset多重集合
multiset 是一种容器,它与set类似,用于存储一组元素,并按照一定的排序规则进行排序。
不同之处在于,multiset容器允许存储重复的元素
multiset的定义和结构与set类似,如下所示:
template <class Key, class Compare = less<key>,
class Allocator = allocator<key>>
class multiset;
- key: 表示存储在set中的元素的类型。
- Compare: 表示元素之间的比较函数对象的类型,默认为less,即按照元素的值进行比较。
- Allcoator: 表示用于分配内存的分配器类型,默认为allocator.
multiset的内部实现也使用红黑树来存储元素,并保持元素的有序性。与set不同的是,multiset中的元素可以重复出现
multiset函数
s.insert(key); //向set中插入一个元素key。
s.erase(key); //从set中移除指定的元素key。
s.find(key); //查找set中是否存在指定的元素key,如果存在则返回指向该元素的迭代器,否则返回set::end()。
s.lower_bound(key); //返回指向第一个不小于给定键值key的元素的迭代器。
s.upper_bound(key); //返回指向第一个大于给定键值key的元素的迭代器。
s.size(); //返回集合中元素的数量
s.empty(); //检查集合是否为空
s.clear(); //清空set中的所有元素。
s.begin(); //指向集合中最小元素的迭代器
s.end(); //指向集合中最大元素的下一个位置的迭代器
s.rebegin(); //返回指向集合末尾位置的逆向迭代器
s.rend(); //返回指向集合起始位置的逆向迭代器
s.swap(); //交换两个集合
s.count(key); //返回set中与指定元素key相等的元素的个数,由于set中不允许有重复的元素,因此返回值只能是0或1。
unordered_set无序集合
unordered_set 是一种容器,用于存储一组唯一的元素,并且没有特定的顺序。unorderde_set容器使用哈希表来实现元素的存储和访问,因此元素的插入、删除和查找的时间复杂度都是常数时间,即O(1)。
unordered_set的定义和结构如下:
template <class key, class Hash = Hash<key>,
class keyEqual = equal_to<key>,
class Allocator = allocator<key>>
class unordered_set;
- key: 表示存储在set中的元素的类型。
- Hash: 表示用于计算元素哈希值的哈希函数对象的类型,默认为hash,使用key类型默认哈希函数
- keyEqual: 表示用于比较元素是否相等的函数对象的类型,默认为equal_to,使用key类型的默认相等比较函数
- Allcoator: 表示用于分配内存的分配器类型,默认为allocator.
- unordered_set 中的元素是唯一的,即不允许重复的元素的存在。当插入一个重复的元素时,unoredered_set会自动忽略该元素。
unordered_set函数
s.insert(key); //向set中插入一个元素key。
s.erase(key); //从set中移除指定的元素key。
s.find(key); //查找set中是否存在指定的元素key,如果存在则返回指向该元素的迭代器,否则返回set::end()。
s.count(key); //返回set中与指定元素key相等的元素的个数,由于set中不允许有重复的元素,因此返回值只能是0或1。
s.size(); //返回集合中元素的数量
代码示例:
#include <iostream>
#include <set>
using namespace std;
int main() {
set<int> mySet;
// 插入元素
mySet.insert(5);
mySet.insert(2);
mySet.insert(8);
mySet.insert(2); // 重复元素,不会被插入,因为set自动去重
// 遍历集合
cout << "Set elements: ";
for (const auto& elem : mySet) {
cout << elem << " ";
}
cout << endl; // 应该输出:2 5 8(注意顺序可能因实现而异,但一定是升序)
// 查找元素
int searchValue = 5;
auto it = mySet.find(searchValue);
if (it != mySet.end()) {
cout << searchValue << " found in the set." << endl;
} else {
cout << searchValue << " not found in the set." << endl;
}
// 移除元素
int removeValue = 2;
mySet.erase(removeValue);
// 再次遍历集合
cout << "Set elements after removal: ";
for (const auto& elem : mySet) {
cout << elem << " ";
}
cout << endl; // 应该输出剩余的元素,例如:5 8(顺序可能因实现而异)
// 清空集合
mySet.clear();
// 检查集合是否为空
if (mySet.empty()) {
cout << "Set is empty." << endl;
} else {
cout << "Set is not empty." << endl;
}
return 0;
}
set板子
#define fi first
#definese second
constint INF Xfffffff:
constint mod = 1e9 + 7;
int N = 2e5 + 10;
void Solved(){
set<int> st;
for(int i=10;i>0;i--) st.insert(i);
//for(const auto&i:st) cout << i<< endl;
for(set<int>::iterator it = st.begin();it != st.end();it ++ ){
cout << *it << endl;
}
signed main(void){
IOS
int ALL =1:
cin >>ALL;
while(ALL --) Solved();
// cout<< fixed;/制以小数形式显示
//cout<< setprecision(n)://保留n位小数
return 0;
}
stack(栈)
stack的定义和结构
stack是一种后进先出(LIFO)的数据结构,使用前需要包含头文件。
stack提供了一组函数来操作和访问元素,但它的功能相对较简单。
stack的定义和结构如下:
template <class T, class CONtainer = deque<T>>
class stack;
stack的常用函数
stack<int> stk;
stk.push(x);//将x加入栈中,即入栈操作
stk.pop();//出栈操作(删除栈顶),只是出栈,没有返回值
stk.top();//返回第一个元素(栈顶元素)
stk.size();//返回栈中的元素个数
stk.empty();//当栈为空时,返回 true
stack不能遍历
如果将数组的元素依次放入栈,再依次取出,则可以将数组翻转
代码示例:
#include <iostream>
#include <stack>
using namespace std;
int main() {
stack<int> myStack;
// 向栈中插入元素
myStack.push(10);
myStack.push(20);
myStack.push(30);
myStack.push(40);
//获取栈顶元素
cout << "栈顶元素:" << myStack.top() << endl;
//弹出栈顶元素
myStack.pop();
//再次获取栈顶元素
cout << "弹出一个元素后的栈顶元素:" << myStack.top() << endl;
// 检查栈是否为空
if (myStack.empty()) {
cout << "栈为空" << endl;
} else {
cout << "栈不为空" << endl;
}
//获取栈的大小
cout << "栈的大小:" << myStack.size() << endl;
return 0;
}
map(映射)
map容器是一个键值对 key - value 的映射。其内部实现是一棵以key为关键码的红黑树。map的key和value可以是任意类型,其中key必须定义“小于号”运算符
map的定义和结构如下:
template<class key, class T, class Compare = less<key>,
class Allocator = allocator<pair<const key, T>>>
class map;
map<long long, bool> vis;
map<string, int> hash;
map<pair<int, int>, vector<int> > test;
在很多时候,map容器被当作Hash表使用,建立从复杂信息key(如字符串)到简单信息value(如一定范围内的整数)的映射。
因为map基于平衡树实现,所以它的大部分操作的时间复杂度都在O(log n)级别,比Hash函数实现的传统Hash表慢。
map函数(常用)
map<string, int> h;
undered_map<string, int> operator;
h.insert() //插入键值对到map中。有多种形式的insert()函数重载,可以接受单个键值对、迭代器范围或者初始化列表作为参数。
h.erase() //从map中删除指定键的键值对。有多种形式的erase()函数重载,可以接受单个键、迭代器范围或者删除满足特定条件的键值对。
h.find() //查找指定键的位置,并返回指向该位置的迭代器。如果键不存在,则返回map的end()迭代器。
h.count() //返回指定键在map中的个数。由于map中的键是唯一的,因此返回值只能是0或1。
//判断key是否存在
h.size() //返回元素个数
h.begin() //返回元素个数
h.end() //返回元素个数
h.empty() //检查map是否为空。如果map为空,则返回true,否则返回false。
h.clear() //清空map,删除所有的键值对。
h.lower_bound() //返回指向第一个不小于指定键的元素位置
h.upper_bound() //返回指向第一个大于指定键的元素位置
multimap
multimap是一种关联容器,类似于map,但允许存储多个具有相同键值对
multimap容器根据键来自动进行排序,并且可以通过键快速查找对应的值
multimap定义结构:
template<class key, class T, class Compare = less<key>,
class Allocator = allocator<pair<const key, T>>>
class multimap;
函数:
map<string, int> h;
undered_map<string, int> operator;
h.insert() //插入键值对到map中。有多种形式的insert()函数重载,可以接受单个键值对、迭代器范围或者初始化列表作为参数。
h.erase() //从map中删除指定键的键值对。有多种形式的erase()函数重载,可以接受单个键、迭代器范围或者删除满足特定条件的键值对。
h.find() //查找指定键的位置,并返回指向该位置的迭代器。如果键不存在,则返回map的end()迭代器。
h.count() //返回指定键在map中的个数。由于map中的键是唯一的,因此返回值只能是0或1。
h.size() //返回map中键值对的个数。
h.empty() //检查map是否为空。如果map为空,则返回true,否则返回false。
h.clear() //清空map,删除所有的键值对。
operator[] //访问指定键的值。如果键存在,则返回对应的值;如果键不存在,则会插入一个新的键值对,关联的值被默认构造。
如果多次查找的key不存在,当时间一长,容器里会多很多无用的0值,占用内存。
在使用 [ ] 操作符之前,最好先用find函数检查key的存在性
使用map容器的示例代码
#include<iostream>
#include<map>
using namespace std;
int main(){
//创建并初始化map
map<int, string> myMap = {{1,"Apple"},{2,"Banana"},{3,"Orange"}};
//插入元素
myMap.insert(make_pair(4,"Grapes"));
//查找和访问元素
cout << "Value at key 2: " << myMap[2] << endl;
//遍历并打印map中的元素
for(const auto& pair : myMap){
cout << "key: " << pair.first << ",Value: " << pair.cond << endl;
}
//删除元素
myMap.erase(3);
//判断元素是否存在
if(myMap.count(3) == 0){
cout << "key 3 not found." << endl;
}
//删除元素
myMap.erase(3);
//判断元素是否存在
if(myMap.count(3) == 0){
cout << "key 3 not found." << endl;
}
//清空map
myMap.clear();
//判断map是否为空
if(myMap.empty()){
cout << "Map is empty." << endl;
}
return 0;
}
使用multimap容器的示例代码
#include<iostream>
#include<map>
using namespace std;
int main(){
//创建并初始化multimap
map<int, string> myMultimap = {{1,"Apple"},{2,"Banana"},{3,"Orange"}};
//插入元素
myMultimap.insert(make_pair(4,"Grapes"));
//查找和访问元素
auto range = myMultimap.equal_range(2);
for(auto it = rang.first; it != range.second; +it){
cout << "key:" << it->first << ",Value:" << it->second <<endl;
}
//遍历并打印Multimap中的元素
for(const auto& pair : myMultimap){
cout << "key: " << pair.first << ",Value: " << pair.cond << endl;
}
//删除元素
myMultimap.erase(3);
//判断元素是否存在
if(myMultimap.count(3) == 0){
cout << "key 3 not found." << endl;
}
//清空map
myMultimap.clear();
//判断map是否为空
if(myMultimap.empty()){
cout << "Map is empty." << endl;
}
return 0;
}
使用unordered_map容器的示例代码
#include <iostream>
#include <unordered_map>
#include <string>
int main() {
// 创建一个unordered_map容器
std::unordered_map<int, std::string> myMap;
// 插入键值对
myMap.insert({1, "one"});
myMap.insert({2, "two"});
myMap[3] = "three";
// 访问值
std::cout << myMap[1] << std::endl; // 输出: one
// 检查键是否存在
if (myMap.count(2) > 0) {
std::cout << "Key 2 exists." << std::endl;
}
// 遍历键值对
for (const auto& pair : myMap) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
// 删除键值对
myMap.erase(3);
return 0;
}
bitset
bitset可看作一个多位二进制,每8位占用一个字节,相当于采用了状态压缩的二进制数组,并支持基本的位运算。在估算程序运行的时间时,我们一般以32位整数的运算次数位基准,因此n位bitset执行一次位运算的复杂度可视为n/32,效率较高
bitset声明时可初始化,可用unsigned或string型来赋值。当用unsing long值作为bitset对象的初始值时,该值将转化为二进制的位模式。 而bitset对象中的位集作为这种位模式的副本。如果bitset类型长度大于unsigned long值的二进制位数,则其余的高阶位置为0;如果bitet类型长度小于unsigned long值的二进制位数,则只使用unsigned值中的低阶位,超过bitet类型长度的高阶位将被丢弃。
操作符
~s : 返回对bitset s按位取反的结果
&,|,^ : 返回丢两个位数相同的bitset执行按位与、或、异或运算的结果
“>>”,“<<”: 返回把一个bitset右移、左移若干位的结果
==,!= : 比较两个bitset代表的二进制数是否相等
bitset支持[ ]操作符,bitset[i]表示二进制的第i位,可以赋值或取值。
//头文件
#include<bitset>
//声明/初始化
bitset<n> s; //表示一个n位的二进制数,每位都是0
bitset<n> s(m) //表示一个n位的二进制数,位m的二进制表示
string s;
bitset<n> s(str) //将string行转化位bitset型,前提时str为01字符串
bitset<n> s(s, a, b) //将字符串s的下标a开始,长度为b的子字符串与bitset进行转换
bitset和string是反向转化的,但仅限与string型小于bitset位数的部分,超出bitset位数的部分将被抛弃,在bitset位数内,string反向转换位bitset型。
bitset与整型数转换时,bitset从第0位开始存储整型数二进制下的最低位,当整型数的二进制位数超过bitset位数时,超出部分将不会被读进。
遇到整型数或者string型转bitset型时,当整型数二进制或string长度小于bitset时,bitset的高阶补0。
举个例子:
整型数15,二进制为0100,0001,正常转换为8位bitset型为1000,0010, string型转换同理
但是如果0100,0001转换为4位bitset型则为: 1000,因为bitset是从15的二进制的第0位开始储存
string型的"01000001"转换位4位bitset型则为: 0010,因为bitset是将string的前四位反向读取,而string的后四位抛弃了
常用内置函数
b.any() //b中是否存在为1的二进制位
b.none() //b中不存在置为1的二进制位
b.count() //b中置为1的二进制位的个数
b.size() //b中二进制位的个数
b.test(x) //b中在x处的二进制是否位1?
b.set() //把b中所有二进制位都置为1
b.set(x) //把b中在x处的二进制位置为1
b.reset() //把b中所有二进制位都置为0
b.reset(x) //把b中在x处的二进制位置为0
b.flip() //把b中所有二进制位逐位取反
b.flip(x) //把b中在x处的二进制位取反
b.to_uiong() //用b中同样的二进制位返回一个unsigned long值
cout << b << endl; //直接输出b
srring(字符串)
string字符串,是c++中的一个类,也可以看作是一个字符串容器,可以说是非常好用。它可以直接将两个字符串进行比较。另外其内置函数功能也是十分齐全。
#include<cstring>
string str;
str.push_back('s');//在末尾添加字符's'
str.pop_back();//删除最后一个元素
str.front();//返回第一个元素
str.back();//返回最后一个元素
str.clear();//清空容器
str.empty();//容器为空时返回true,否则返回flase
str.erase(3);//删除str[3]~str[n - 1],返回str
str.erase(2, 3);//删除str[2]~str[2+3-1]
str.erase(str.begin());//删除指向的元素, 返回迭代器, 指向下一元素
str.erase(str.begin(), str.end());//删除区间内的元素, 返回迭代器, 指向下一元素
str.find('s');//返回字符 ‘s’ 在 str 中首次出现的位置
str.find('s', 2);//返回字符 ‘s’ 在 str[2]~str[n-1] 中首次出现的位置
str.find(ch);//返回字符串 ch 在 str 中首次出现的位置
str.find(ch, 4);//返回 ch 在 str[4]~str[n-1] 中首次出现的位置
str.find(ch, 4, 3);//返回 ch[0]~ch[3-1] 在 str[4]~str[n-1] 中首次出现的位置
str.find(str1);//返回 str1 在 str 中首次出现的位置
str.find(str1, 2);//返回 str1 在 str[2]~str[n-1] 中首次出现的位置
str.substr(2);//返回 str[2]~str[n-1], 不对 str 进行操作
str.substr(2,3);//返回 str[2]~str[2+3-1]
stringstream
srd::stringstream
是C++标准库中的一个类,它提供了字符串流的功能,可以将数据以字符串的形式进行输入和输出。std::stringstream
可以将各种类型的数据转换为字符串,并且可以从字符串中提取数据。
#include<iostream>
#include<algorithm>
#include<sstream>
using namespace std;
int main(){
//1、创建一个对象,向对象输入字符串,输入字符串后直接进行字符串拼接
stringstream ss;
ss << str;
ss1 << "fre";
ss3 << "gre";
cout << ss1.str() << edml;
//2、创建时使用字符串初始化,进行字符串拼接时,首先把原本的字符串覆盖掉,之后再进行拼接。
stringstream ss(str);
//3、输出时需调用str()函数
cout << ss.str() << endl;
//4、利用stringstream去除字符串空格,streamstring 默认是以空格来分割字符串
stringstream ss("2 dfjho 43");
cout << ss.str() << endl;
string str;
while (ss >> str){
cout << str << endl;
}
//5、利用 streamstring 指定字符分割字符串
string source = "abc,123,<!>";
stringstream ss(source);
cout << ss.str() << endl;
cout<< endl;
string str;
while (getline(ss, str, ',')){
cout << str << endl;
}
}
}
std::stringstream
还提供了其他一些功能,如clear()
函数用于重置字符串流的状态,str()
函数用于获取字符串流的内容,以及seekg()
和seekp()
函数用于设置读写位置。
std::stringstream
对于将数据转换为字符串或从字符串中提取数据非常有用,尤其在需要处理字符串形式的数据时。
pair(二元组)
pair的定义和结构
在C++中,pair是一个模板类,用于表示一对值的组合。它位于<utility>
头文件中。
pair类的定义如下:
template<class T1, class T2>
struct pair{
T1 first; //第一个值
T2 second; //第二个值
//构造函数
pair();
pair(const T1& x, const T2& y);
//比较运算符重载
bool operator == (const pair& rhs) const;
bool operator != (const pair& rsh) const;
//其他成员函数的特征
......
}
C++内置二元组,其中包含两个元素,分别是first、second。在比较大小中,以第一元first尾第一关键字,第二元second尾第二关键字。
pair<int> a; //a为int型的二元组
a.first = 1; a.second = 2;
pair<int, pair<int, int>> b;
b.first = 1;
b.second.first = 2; b.second.second = 3;
list
list的定义和结构
list是一种双向链表容器,它是标准模板库STL提供的一种序列容器,list容器以节点(node) 的形式存储元素,并使用指针将这些节点链接在一起,形成一个链表结构。
list容器的特点包括:
-
双向性:每个节点都包含指向前一个节点和后一个节点的指针,因此可以在常数时间内在链表中的任意位置进行插入、删除和访问操作。
-
动态大小:链表的大小可以根据需要动态扩展或收缩,不需要预先 指定容器的大小。
-
不连续存储:链表中的节点可以在内存中的任意位置分布,不要求连续存储,因此插入和删除操作不会导致元素的移动
list容器提供了一系列成员函数和迭代器来操作和访问链表中的元素,包括插入、删除、访问、反转等操作。可以使用迭代器来遍历链表中的元素。
展示list容器
#include<iostream> #include<list> using namespace std; int main(){ list<int> myList; //在链表尾部插入元素 myList.push_back(1); myList.push_back(2); myList.push_back(3); //在链表头部插入元素 myList.push_front(0); //遍历链表并输出元素 for(int num : myList){ cout << num << " "; } cout << endl; return 0; }
list常用函数
list<int> myList; myList.push_back(); //将元素插入到链表的末尾 myList.push_front(); //将元素插入到链表的开头 myList.pop_back(); //移除链表末尾的元素 myList.pop_front(); //移除链表开头的元素 myList.size(); //返回链表中元素的个数 myList.empty(); //检查链表是否为空 myList.clear(); //清空链表的所有元素 myList.front(); //返回链表中第一个元素的引用 myList.back(); //返回链表中最后一个元素的引用 myList.begin(); //返回指向链表第一个元素的迭代器 myList.end(); //返回指向链表末尾的下一个位置的迭代器 myList.insert(); //在指定位置之前插入一个或多个元素 myList.erase(); //从链表中移除指定位置的一个或多个元素
代码示例:
#include<bits/stdc++.h> using namespace std; int main() { //创建一个List<int> 对象myList list<int> myList; //向myList尾部添加元素 for(int i = 1; i <= 5; i++) { myList.push_back(i); } //从头到尾输出myList中的元素 for(const auto &i : myList) cout << i << " "; cout << endl; //将myList中的元素反转 reverse(myList.begin(), myList.end()); for(const auto &i : myList) cout << i << " "; cour << endl; //在第一个元素的后一个位置加上元素0 myList.insert(++myList.begin(), 0); for(const auto &i : myList) cout << i << " "; cout << endl; myList.erase(++ ++ myList.begin(), --myList.end()); //输出myList的大小 cout << myList.size() << "\n"; //从头到位输出myList中的元素 for(const auto &i : myList) cout << i << " "; cout << "\n"; return 0; }
结果
1 2 3 4 5 5 4 3 2 1 5 0 4 3 2 1 链表大小为:3 5 0
二分查找函数
lower_bound()
lower_bound() 函数定义在头文件中,其语法格式有 2 种,分别为:
//在 [first, last) 区域内查找不小于 val 的元素
ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last, const T& val);
//在 [first, last) 区域内查找第一个不符合 comp 规则的元素
ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last, const T& val, Compare comp);
其中,first 和 last 都为正向迭代器,[first, last) 用于指定函数的作用范围;val 用于指定目标元素;comp 用于自定义比较规则,此参数可以接收一个包含 2 个形参(第二个形参值始终为 val)且返回值为 bool 类型的函数,可以是普通函数,也可以是函数对象。
实际上,第一种语法格式也设定有比较规则,只不过此规则无法改变,即使用 < 小于号比较 [first, last) 区域内某些元素和 val 的大小,直至找到一个不小于 val 的元素。这也意味着,如果使用第一种语法格式,则 [first,last) 范围的元素类型必须支持 < 运算符。
此外,该函数还会返回一个正向迭代器,当查找成功时,迭代器指向找到的元素;反之,如果查找失败,迭代器的指向和 last 迭代器相同。
upper_bound()
pper_bound() 函数定义在头文件中,用于在指定范围内查找大于目标值的第一个元素。该函数的语法格式有 2 种,分别是:
//查找[first, last)区域中第一个大于 val 的元素。
ForwardIterator upper_bound (ForwardIterator first, ForwardIterator last, const T& val);
//查找[first, last)区域中第一个不符合 comp 规则的元素
ForwardIterator upper_bound (ForwardIterator first, ForwardIterator last, const T& val, Compare comp);