C++进阶语法——STL 标准模板库(下)(Standard Template Library)【学习笔记(七)】
文章目录
- STL 代码示例
- 1、迭代器
- 2、算法
- 3、array容器示例
- 4、vector示例
- 5、deque(double ended queue,双端数组)示例
- 6、list(链表)容器
- 7、set示例
- 8、map示例
- 9、stack 示例
- 10、queue示例
- 11、priority_queue (优先级队列)示例
STL 代码示例
1、迭代器
- 迭代器可以将任意的容器抽象成一个序列,可以使用迭代器遍历容器中的元素
- 迭代器设计的目的是为了解决容器与算法之间的耦合问题,与指针类似,可以通过迭代器访问容器中的元素
- 迭代器的声明方式为:容器类型::iterator 变量名称,可以理解为一个普通的指针,比如:
- std::vector<int>::iterator it;
- std::list<int>::iterator it;
- std::map<int, int>::iterator it;
- std::set<int>::iterator it;
代码:
/*
* 迭代器示例
* 迭代器可以将任意的容器抽象成一个序列,可以使用迭代器遍历容器中的元素
* 迭代器设计的目的是为了解决容器与算法之间的耦合问题,与指针类似,可以通过迭代器访问容器中的元素* 迭代器的声明方式为:容器类型::iterator,比如:std::vector<int>::iterator it;
std::list<int>::iterator it;
std::map<int, int>::iterator it;
std::set<int>::iterator it;*/
#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <list>// 打印vector元素
void printVec(const std::vector<int> &v)
{std::cout << "[";for (const auto &e : v)std::cout << e << " ";std::cout << "]" << std::endl;
}void test1()
{std::cout << "test1 ======================" << std::endl;std::vector<int> v1 {1, 2, 3, 4, 5};std::vector<int>::iterator it = v1.begin(); // 指向第一个元素std::cout << *it << std::endl;it++; // 指向第二个元素std::cout << *it << std::endl;it += 2; // 指向第四个元素std::cout << *it << std::endl;it -= 2; // 指向第二个元素std::cout << *it << std::endl;it = v1.end() - 1; // 指向最后一个元素,注意end()指向最后一个元素的下一个位置std::cout << *it << std::endl;}void test2()
{std::cout << "test2 ======================" << std::endl;std::vector<int> v1 {1, 2, 3, 4, 5};auto it = v1.begin();while (it != v1.end()){std::cout << *it << std::endl;it++; // 指向下一个元素}it = v1.begin();while (it != v1.end()){*it = 100; // 修改元素值it++;}printVec(v1);}void test3()
{std::cout << "test3 ======================" << std::endl;std::vector<int> v1 {1, 2, 3, 4, 5};// std::vector<int>::const_iterator it = v1.begin(); // 常量迭代器,只能读取元素,不能修改元素auto it = v1.cbegin(); // 如果使用auto,需要使用cbegin()函数,返回一个常量迭代器while (it != v1.end()){std::cout << *it << std::endl;it++; // 指向下一个元素}it = v1.begin(); // 重新指向第一个元素while (it != v1.end()){// *it = 100; // 报错,不能修改元素it++; // 指向下一个元素}}void test4()
{std::cout << "test4 ======================" << std::endl;std::vector<int> v1 {1, 2, 3, 4, 5};auto it = v1.rbegin(); // 返回一个反向迭代器,指向最后一个元素while (it != v1.rend()) // rend()指向第一个元素的前一个位置{std::cout << *it << std::endl;it++; // 指向下一个元素}std::list<std::string> l1 {"hello", "world", "c++"};auto it2 = l1.rbegin();std::cout << *it2 << std::endl;it2++;std::cout << *it2 << std::endl;// map 里面的元素会自动按 key 进行排序std::map<std::string, std::string> m1 {{"hello", "你好"},{"world", "世界"},{"Computer", "计算机"}};auto it3 = m1.begin();while (it3 != m1.end()){std::cout << it3->first << " : " << it3->second << std::endl;it3++;}}
int main()
{// test1();// test2();// test3();test4();return 0;
}
2、算法
- STL算法基于迭代器生成的序列
- STL提供了很多算法(例如查找、排序、计数、操作),可以对序列进行操作
- 更多请查看:https://zh.cppreference.com/w/cpp/algorithm
- 多数算法要求提供额外参数,例如:排序算法需要提供排序规则,一般使用函数指针、lambda表达式或仿函数(函数对象)
代码:
/*
* 算法示例
* STL算法基于迭代器生成的序列
* STL提供了很多算法(例如查找、排序、计数、操作),可以对序列进行操作
* 更多请查看:https://zh.cppreference.com/w/cpp/algorithm
* 多数算法要求提供额外参数,例如:排序算法需要提供排序规则,一般使用函数指针、lambda表达式或仿函数(函数对象)
*/#include <iostream>
#include <vector>
#include <algorithm> // 算法头文件
#include <list>void test1()
{std::cout << "test1 ======================" << std::endl;std::vector<int> v1{1, 2, 3, 4, 5};std::vector<int>::iterator loc = std::find(v1.begin(), v1.end(), 3); // 查找3std::cout << *loc << std::endl; // 3std::cout << *v1.end() << std::endl; // 0if (loc != v1.end())std::cout << "找到 3" << std::endl;elsestd::cout << "未找到 3" << std::endl;
}void test2()
{std::cout << "test2 ======================" << std::endl;std::vector<int> v1{1, 2, 3, 4, 5, 1, 2, 1};int counts = std::count(v1.begin(), v1.end(), 1); // 统计1的个数std::cout << "1的个数: " << counts << std::endl;
}// 判断是否是偶数
bool isEven(int x)
{return x % 2 == 0;
}
void test3()
{std::cout << "test3 ======================" << std::endl;std::vector<int> v1{1, 2, 3, 4, 5, 6, 7, 8, 9};int counts = std::count_if(v1.begin(), v1.end(), isEven); // 使用函数指针统计偶数个数counts = std::count_if(v1.begin(), v1.end(), [](int x){ return x % 2 == 0; }); // 使用lambda表达式统计偶数个数std::cout << "偶数个数: " << counts << std::endl;counts = std::count_if(v1.begin(), v1.end(), [](int x){ return x > 6; }); // 统计大于6的个数std::cout << "大于6的个数: " << counts << std::endl;
}void test4()
{std::cout << "test4 ======================" << std::endl;std::vector<int> v1{1, 2, 3, 4, 5, 1, 2, 1};for (const auto &e : v1)std::cout << e << " ";std::cout << std::endl;std::replace(v1.begin(), v1.end(), 1, 100); // 将1替换为100for (const auto &e : v1)std::cout << e << " ";std::cout << std::endl;
}void test5()
{std::cout << "test5 ======================" << std::endl;std::vector<int> v1{1, 2, 3, 4, 5, 6, 7, 8, 9};if (std::all_of(v1.begin(), v1.end(), [](int x) { return x > 5; }) ) // 所有元素都大于5std::cout << "所有元素都大于5" << std::endl;elsestd::cout << "不是所有元素都大于5" << std::endl;if (std::any_of(v1.begin(), v1.end(), [](int x) { return x > 5; }) ) // 至少有一个元素大于5std::cout << "有元素大于5" << std::endl;elsestd::cout << "没有元素大于5" << std::endl;if (std::none_of(v1.begin(), v1.end(), [](int x) { return x < 0; }) ) // 没有元素小于0std::cout << "没有元素小于0" << std::endl;elsestd::cout << "有元素小于0" << std::endl;}void test6()
{std::cout << "test6 ======================" << std::endl;std::string s1 {"hello world"};std::cout << s1 << std::endl;std::transform(s1.begin(), s1.end(), s1.begin(), ::toupper); // 转换为大写,从s1的begin到end,转换后的结果放到s1的beginstd::cout << s1 << std::endl;}
int main()
{test1();// test2();// test3();// test4();// test5();// test6();return 0;
}
3、array容器示例
- array大小固定,不可改变
- 在内存中是连续的
- 获取元素的复杂度是常数,与array元素个数无关
- 是对原始数组的封装,也可以获取原始数组的指针
- 如果数组大小固定,尽量使用array,而不是使用C++原生数组,因为array可以使用标准库的算法
代码:
/*
* array容器示例
* array大小固定,不可改变
* 在内存中是连续的
* 获取元素的复杂度是常数,与array元素个数无关
* 是对原始数组的封装,也可以获取原始数组的指针
* 如果数组大小固定,尽量使用array,而不是使用C++原生数组,因为array可以使用标准库的算法
*/#include <iostream>
#include <array> // 使用array容器
#include <algorithm>
#include <numeric> // 打印数组
void display(const std::array<int,5> &arr)
{std::cout << "[ ";for (const auto &a: arr)std::cout << a << " ";std::cout << "]" << std::endl;
}void test1()
{std::cout << "test1 ======================" << std::endl;std::array<int, 5> arr1 {1, 2, 3, 4, 5};std::array<int, 5> arr2;display(arr1);display(arr2); // 未初始化,值为随机值arr2 = {10, 20, 30, 40, 50}; // 可以直接赋值display(arr1);display(arr2); std::cout << "arr1的大小:" << arr1.size() << std::endl;std::cout << "arr2的大小:" << arr2.size() << std::endl;arr1[0] = 1000;arr1.at(1) = 2000;display(arr1);std::cout << "arr1的第一个元素:" << arr1.front() << std::endl;std::cout << "arr1的最后一个元素:" << arr1.back() << std::endl;}void test2()
{std::cout << "test2 ======================" << std::endl;std::array<int, 5> arr1 {1, 2, 3, 4, 5};std::array<int, 5> arr2 {10, 20, 30, 40, 50};display(arr1);display(arr2);arr1.fill(0);display(arr1);display(arr2);arr1.swap(arr2);display(arr1);display(arr2);}void test3()
{std::cout << "test3 ======================" << std::endl;std::array<int, 5> arr1 {1, 2, 3, 4, 5};int *ptr = arr1.data(); // 返回数组的首地址std::cout << ptr << std::endl;std::cout << *ptr << std::endl;*ptr = 1000;display(arr1);
}void test4()
{std::cout << "test4 ======================" << std::endl;std::array<int, 5> arr1 {3,1,4,2,5};display(arr1);std::sort(arr1.begin(), arr1.end());display(arr1);
}void test5()
{std::cout << "test5 ======================" << std::endl;std::array<int, 5> arr1 {3,6,4,2,5};std::array<int, 5>::iterator min_val = std::min_element(arr1.begin(), arr1.end());auto max_val = std::max_element(arr1.begin(), arr1.end());std::cout << "min: " << *min_val << std::endl;std::cout << "max: " << *max_val << std::endl;
}void test6()
{std::cout << "test6 ======================" << std::endl;std::array<int, 5> arr1 {3,6,2,2,5};auto adjacent = std::adjacent_find(arr1.begin(), arr1.end()); // 查找相邻的两个相同的元素if (adjacent != arr1.end())std::cout << "adjacent: " << *adjacent << std::endl;elsestd::cout << "没有找到相邻的两个相同的元素" << std::endl;}void test7()
{std::cout << "test7 ======================" << std::endl;std::array<int, 5> arr1 {1,2,3,4,5};int sum = std::accumulate(arr1.begin(), arr1.end(), 0); // 求和std::cout << "sum: " << sum << std::endl;}void test8()
{std::cout << "test8 ======================" << std::endl;std::array<int, 10> arr1 {1,2,3,4,5,5,5,5,5,5};int counts = std::count(arr1.begin(), arr1.end(), 5); // 统计5的个数std::cout << "5一共出现了" << counts << "次" << std::endl;
}
int main()
{// test1();// test2();// test3();// test4();// test5();// test6();// test7();test8();return 0;
}
4、vector示例
- vector是一个动态数组,可以随意增加元素
- 与array一样,vector在内存中是连续的,对应的内存空间会随着元素的增加而增加
- 获取元素的复杂度是常数,与vector的大小无关
- 在vector末尾增加、删除元素的复杂度是常数,与vector的大小无关
- 在vector中间增加、删除元素的复杂度是线性的,与vector的大小有关
- 可以使用迭代器和算法
代码:
/*
* vector示例
* vector是一个动态数组,可以随意增加元素
* 与array一样,vector在内存中是连续的,对应的内存空间会随着元素的增加而增加
* 获取元素的复杂度是常数,与vector的大小无关
* 在vector末尾增加、删除元素的复杂度是常数,与vector的大小无关
* 在vector中间增加、删除元素的复杂度是线性的,与vector的大小有关
* 可以使用迭代器和算法
*/#include <iostream>
#include <vector>
#include <algorithm>// 打印vector的函数模板
template <typename T>
void printVector(const std::vector<T> &v)
{std::cout << "[";for (const auto &e : v)std::cout << e << " ";std::cout << "]" << std::endl;
}void test1()
{std::cout << "test1 ======================" << std::endl;std::vector<int> v1{1, 2, 3, 4, 5};printVector(v1);v1 = {10, 20, 30, 40, 50}; // 可以直接赋值printVector(v1);std::vector<int> v2(10, 88); // 10个88printVector(v2);
}void test2()
{std::cout << "test2 ======================" << std::endl;std::vector<int> v1{1, 2, 3, 4, 5};printVector(v1);std::cout << "size: " << v1.size() << std::endl; // 大小std::cout << "capacity: " << v1.capacity() << std::endl; // 容量std::cout << "max_size: " << v1.max_size() << std::endl; // 最大容量v1.push_back(6); // 在尾部添加元素printVector(v1);std::cout << "size: " << v1.size() << std::endl; // 大小std::cout << "capacity: " << v1.capacity() << std::endl; // 容量,每超出一次,容量翻倍std::cout << "max_size: " << v1.max_size() << std::endl; // 最大容量v1.shrink_to_fit(); // 释放多余的内存printVector(v1);std::cout << "size: " << v1.size() << std::endl; // 大小std::cout << "capacity: " << v1.capacity() << std::endl; // 容量,释放多余的内存后,容量恢复到size大小std::cout << "max_size: " << v1.max_size() << std::endl; // 最大容量v1.reserve(100); // 预留100个元素的空间printVector(v1);std::cout << "size: " << v1.size() << std::endl; // 大小std::cout << "capacity: " << v1.capacity() << std::endl; // 容量,预留100个元素的空间后,容量恢复到100,直到超出100std::cout << "max_size: " << v1.max_size() << std::endl; // 最大容量
}void test3()
{std::cout << "test3 ======================" << std::endl;std::vector<int> v1{1, 2, 3, 4, 5};printVector(v1);v1[0] = 100;v1.at(1) = 200;printVector(v1);std::cout << "v1的第一个元素: " << v1.front() << std::endl;std::cout << "v1的最后一个元素: " << v1.back() << std::endl;v1.pop_back(); // 删除最后一个元素printVector(v1);
}void test4()
{std::vector<int> v1{1, 2, 3, 4, 5};printVector(v1);v1.clear(); // 清空容器printVector(v1);v1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};printVector(v1);v1.erase(v1.begin(), v1.begin() + 3); // 删除前三个元素printVector(v1);// 删除所有偶数v1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};std::vector<int>::iterator it = v1.begin(); // 获取迭代器while (it != v1.end()){if (*it % 2 == 0)v1.erase(it);elseit++;}printVector(v1);
}void test5()
{std::cout << "test5 ======================" << std::endl;// 交换两个vectorstd::vector<int> v1{1, 2, 3, 4, 5};std::vector<int> v2{10, 20, 30, 40, 50};printVector(v1);printVector(v2);v1.swap(v2);printVector(v1);printVector(v2);
}void test6()
{std::cout << "test6 ======================" << std::endl;std::vector<int> v1{9, 2, 5, 4, 7, 6, 8, 1, 3};printVector(v1);std::sort(v1.begin(), v1.end()); // 排序printVector(v1);
}// 判断是否为偶数
int getEven(int x)
{return x % 2 == 0;
}void test7()
{std::cout << "test7 ======================" << std::endl;std::vector<int> v1{1, 2, 3, 4, 5};std::vector<int> v2{10, 20};printVector(v1);printVector(v2);std::copy(v1.begin(), v1.end(), std::back_inserter(v2)); // 拷贝printVector(v1);printVector(v2);v1 = {1, 2, 3, 4, 5};v2 = {10, 20};// std::copy_if(v1.begin(),v1.end(),std::back_inserter(v2),getEven); // 拷贝偶数std::copy_if(v1.begin(), v1.end(), std::back_inserter(v2), [](int x){ return x % 2 == 0; }); // 使用lambda表达式printVector(v1);printVector(v2);
}void test8()
{std::cout << "test8 ======================" << std::endl;std::vector<int> v1{1, 2, 3, 4, 5};std::vector<int> v2{10, 20, 30, 40, 50};std::vector<int> v3;std::transform(v1.begin(), v1.end(), v2.begin(), std::back_inserter(v3),[](int x, int y){ return x + y; }); // 加法// std::transform(v1.begin(), v1.end(), v2.begin(), std::back_inserter(v3), std::plus<int>()); // 使用内置的加法函数std::cout << "v1 + v2 = " << std::endl;printVector(v3);v3.clear(); // 清空容器std::transform(v1.begin(), v1.end(), v2.begin(), std::back_inserter(v3),[](int x, int y){ return x * y; }); // 乘法// std::transform(v1.begin(), v1.end(), v2.begin(), std::back_inserter(v3), std::multiplies<int>()); // 使用内置的乘法函数std::cout << "v1 * v2 = " << std::endl;printVector(v3);
}void test9()
{std::cout << "test9 ======================" << std::endl;std::vector<int> v1{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};std::vector<int> v2{100, 200, 300, 400};printVector(v1);printVector(v2);auto it = std::find(v1.begin(), v1.end(), 5); // 查找5第一次出现的位置if (it != v1.end()){std::cout << "找到了:5 " << std::endl;v1.insert(it, v2.begin(), v2.end()); // 插入}else{std::cout << "没有找到" << std::endl;}printVector(v1);
}
int main()
{// test1();// test2();// test3();// test4();// test5();// test6();// test7();// test8();test9();return 0;
}
5、deque(double ended queue,双端数组)示例
- 动态数组,和vector类似,但是deque是双端的,可以在头部和尾部进行插入和删除操作
- 与vector不同,deque在内存中是分段连续的,每段内存都是连续的,所以在头部和尾部插入和删除元素都很快
- 获取元素的复杂度是常数
- 在头部和尾部插入和删除元素的复杂度是常数
- 在中间插入和删除元素的复杂度是线性的
- 支持迭代器和算法
代码:
/*
* deque(double ended queue,双端数组)示例
* 动态数组,和vector类似,但是deque是双端的,可以在头部和尾部进行插入和删除操作
* 与vector不同,deque在内存中是分段连续的,每段内存都是连续的,所以在头部和尾部插入和删除元素都很快
* 获取元素的复杂度是常数
* 在头部和尾部插入和删除元素的复杂度是常数
* 在中间插入和删除元素的复杂度是线性的
* 支持迭代器和算法
*/
#include <iostream>
#include <deque>
#include <vector>
#include <algorithm>// 用于显示deque的函数模板
template <typename T>
void display(const std::deque<T> &d)
{std::cout << "[ ";for (const auto &item:d )std::cout << item << " ";std::cout << "]";std::cout << std::endl;
}void test1()
{std::cout << "test1 ======================" << std::endl;std::deque<int> d1{1, 2, 3, 4, 5};display(d1);std::deque<int> d2 (10,100);display(d2);d2[0] = 99;d2.at(1) = 88;display(d2);
}void test2()
{std::cout << "test2 ======================" << std::endl;std::deque<int> d1 {0,0,0,0};display(d1);d1.push_back(10);d1.push_back(20);display(d1);d1.push_front(100);d1.push_front(200);display(d1);std::cout << "第一个元素: " << d1.front() << std::endl;std::cout << "最后一个元素: " << d1.back() << std::endl;std::cout << "大小: " << d1.size() << std::endl;d1.pop_back();d1.pop_front();display(d1);
}void test3()
{std::cout << "test3 ======================" << std::endl;std::vector<int> v1 {1,2,3,4,5,6,7,8,9,10};std::deque<int> d2;// 将vector中的偶数放入deque后,奇数放入deque前for (const auto &item:v1){if (item % 2 == 0)d2.push_back(item);elsed2.push_front(item);}display(d2);
}void test4()
{std::cout << "test4 ======================" << std::endl;std::vector<int> v1 {1,2,3,4,5,6,7,8,9,10};std::deque<int> d2;// 将vector中的元素放到d2后for (const auto &item:v1)d2.push_back(item);display(d2);d2.clear(); // 清空deque// 将vector中的元素放到d2前for (const auto &item:v1)d2.push_front(item);display(d2);}void test5()
{std::cout << "test5 ======================" << std::endl;std::vector<int> v1 {1,2,3,4,5,6,7,8,9,10};std::deque<int> d2;// 使用std::copy实现test4效果std::copy(v1.begin(), v1.end(), std::back_inserter(d2));display(d2);d2.clear(); // 清空dequestd::copy(v1.begin(), v1.end(), std::front_inserter(d2));display(d2);
}
int main()
{// test1();// test2();// test3();// test4();test5();return 0;
}
6、list(链表)容器
- 动态大小
- list是一个双向链表,支持快速的插入和删除操作
- list不支持随机访问,不支持下标运算符
代码:
/*
* list(链表)容器
* 动态大小
* list是一个双向链表,支持快速的插入和删除操作
* list不支持随机访问,不支持下标运算符
*/#include <iostream>
#include <list>
#include <algorithm>// 打印list的函数模板
template <typename T>
void printList(const std::list<T> &l)
{std::cout << "[";for (const auto &e : l)std::cout << e << " ";std::cout << "]" << std::endl;
}void test1()
{std::cout << "test1 ======================" << std::endl;std::list<int> l1 {1, 2, 3, 4, 5};printList(l1);std::list<std::string> l2;l2.push_back("hello");l2.push_back("world");printList(l2);std::list<int> l3;l3 = {1,2,3,4,5,6,7,8,9,10};printList(l3);std::list<int> l4 (10,88);printList(l4);}void test2()
{std::cout << "test2 ======================" << std::endl;std::list<int> l1 {1,2,3,4,5,6,7,8,9,10};printList(l1);std::cout << "第一个元素: " << l1.front() << std::endl;std::cout << "最后一个元素: " << l1.back() << std::endl;std::cout << "大小: " << l1.size() << std::endl;l1.clear();printList(l1);std::cout << "大小: " << l1.size() << std::endl;
}void test3()
{std::cout << "test3 ======================" << std::endl;std::list<int> l1 {1,2,3,4,5,6,7,8,9,10};printList(l1);l1.resize(5); // 缩小到5个元素printList(l1);
}void test4()
{std::cout << "test4 ======================" << std::endl;std::list<int> l1 {1,2,3,4,5,6,7,8,9,10};printList(l1);// 找到第一个5,然后在5前面追加一个100std::list<int>::iterator it = std::find(l1.begin(), l1.end(), 5);if (it != l1.end())l1.insert(it, 100);printList(l1);std::list<int> l2 {1000, 2000, 3000};// 将l2中的元素插入到l1中l1.insert(it, l2.begin(), l2.end());printList(l1);std::advance(it, -2); // it向前移动2个位置std::cout << *it << std::endl;l1.erase(it); // 删除it指向的元素,也就是2000printList(l1);
}void test5()
{std::cout << "test5 ======================" << std::endl;std::list<int> l1 {3,5,2,10,7,9,8,1,4,6};printList(l1);l1.sort();printList(l1);}
int main()
{// test1();// test2();// test3();// test4();test5();return 0;
}
7、set示例
- set是一种关联式容器
- 根据元素的值,自动排序,重复元素会被自动去重
- 不支持随机访问,不支持下标运算符
- 支持各种迭代器和算法
代码:
/*
* set示例
* set是一种关联式容器
* 根据元素的值,自动排序,重复元素会被自动去重
* 不支持随机访问,不支持下标运算符
* 支持各种迭代器和算法*/
#include <iostream>
#include <set>// 用于显示set的函数模板
template <typename T>
void printSet(const std::set<T> &s)
{std::cout << "[";for (const auto &e : s)std::cout << e << " ";std::cout << "]" << std::endl;
}void test1()
{std::cout << "test1 ======================" << std::endl;std::set<int> s1{1, 2, 3, 4, 5};printSet(s1);s1 = {1,1,1,2,2,2,3,3,3}; // 重复元素会被自动去重printSet(s1);s1.insert(10); s1.insert(0);printSet(s1);if (s1.count(10)) // count返回1表示找到,返回0表示未找到std::cout << "找到10" << std::endl;elsestd::cout << "未找到10" << std::endl;auto it = s1.find(10); // find返回迭代器,如果找到,返回迭代器指向该元素,否则返回end()if (it != s1.end())std::cout << "找到" << *it << std::endl;s1.clear();printSet(s1);
}void test2()
{std::cout << "test2 ======================" << std::endl;std::set<std::string> s1 {"A", "B", "C", "D", "E"};printSet(s1);auto result = s1.insert("F"); // insert返回一个pair,第一个元素是迭代器,指向插入的元素,第二个元素是bool,表示是否插入成功printSet(s1);std::cout << std::boolalpha; // boolalpha表示输出true/falsestd::cout << "first: " << *(result.first) << std::endl;std::cout << "second: " << result.second << std::endl; // 插入成功,返回trueresult = s1.insert("A"); // A 已经存在,插入失败,但是返回的迭代器指向AprintSet(s1);std::cout << std::boolalpha; // boolalpha表示输出true/falsestd::cout << "first: " << *(result.first) << std::endl;std::cout << "second: " << result.second << std::endl; // 插入失败,返回false,表示有重复元素}int main()
{// test1();test2();return 0;
}
8、map示例
- map是一种关联式容器,它的元素是key-value对(std::pair),key是唯一的,value可以重复
- map中的元素是按key自动排序的
- 使用key访问元素
代码:
/*
* map示例
* map是一种关联式容器,它的元素是key-value对(std::pair),key是唯一的,value可以重复
* map中的元素是按key自动排序的
* 使用key访问元素*/#include <iostream>
#include <map>
#include <set>// 打印map的函数模板
template <typename T1, typename T2>
void printMap(const std::map<T1, T2> &m)
{std::cout << "[";for (const auto &e : m)std::cout << e.first << ":" << e.second << " ";std::cout << "]" << std::endl;
}// map的value是set
void printMap(const std::map<std::string, std::set<int>> &m)
{std::cout << "[";for (const auto &e : m){std::cout << e.first << ":[ ";for (const auto &s : e.second)std::cout << s << " ";std::cout << "] ";}std::cout << "]" << std::endl;
}void test1()
{std::cout << "test1 ======================" << std::endl;std::map<std::string, int> m1 { // string是key,int是value{"mike", 10},{"jane", 20},{"tom", 30},};printMap(m1); // [jane:20 mike:10 tom:30 ],会自动按key排序m1.insert(std::pair<std::string, int>("anna", 100)); // 插入一个pairprintMap(m1); m1.insert(std::make_pair("bob", 200)); // 插入一个pairprintMap(m1);m1["jim"] = 300; // 如果key不存在,会自动插入一个pair,如果key存在,会更新valueprintMap(m1);m1["jim"] += 100; // 更新valueprintMap(m1);std::cout << "mike的计次:" << m1.count("mike") << std::endl; // count返回1表示找到,返回0表示未找到std::cout << "alice的计次:" << m1.count("alice") << std::endl; auto it = m1.find("jim"); // find返回迭代器,如果未找到,返回end()if (it != m1.end())std::cout << "找到" << it->first << ",value为" << it->second << std::endl;elsestd::cout << "未找到jim" << std::endl;m1.clear(); // 清空mapprintMap(m1);}void test2()
{std::cout << "test2 ======================" << std::endl;std::map<std::string, std::set<int>> student_grades { // string是key,set是value{"mike", {100, 90}},{"jane", {99, 88, 77}},{"tom", {98, 87, 76}},};printMap(student_grades);student_grades["mike"].insert(80); // 插入80分printMap(student_grades);auto it = student_grades.find("jane");if (it != student_grades.end()){it->second.erase(88); // 删除88分printMap(student_grades);}}int main()
{// test1();test2();return 0;
}
9、stack 示例
- stack 是一种容器适配器,遵循后进先出(LIFO)的原则
- stack 本身不是容器,它是基于容器实现的(如vector、list、deque等)
- 所有的操作都在栈顶进行(top)
- stack 本身没有迭代器
代码:
/*
* stack 示例
* stack 是一种容器适配器,遵循后进先出(LIFO)的原则
* stack 本身不是容器,它是基于容器实现的(如vector、list、deque等)
* 所有的操作都在栈顶进行(top)
* stack 本身没有迭代器
*/#include <iostream>
#include <stack>
#include <vector>
#include <list>
#include <deque>// 显示stack的函数模板
template <typename T>
void display(std::stack<T> s)
{std::cout << "[";while (!s.empty()){T elem = s.top(); // 读取栈顶元素std::cout << elem << " ";s.pop(); // 弹出栈顶元素}std::cout << "]" << std::endl;
}
int main()
{std::stack<int> s;for (auto i: {1,2,3,4,5})s.push(i);display(s);s.push(100); // 压入元素display(s);s.pop(); // 弹出元素s.pop();display(s);// s.clear(); // 并没有clear()方法while (!s.empty())s.pop(); // 弹出所有元素display(s);s.push(10);display(s);s.top() = 100; // 修改栈顶元素display(s);return 0;
}
10、queue示例
- queue是一种容器适配器,遵循先进先出(FIFO)的原则
- queue的底层容器可以是deque、list
- 元素只能从队尾压入,从队首弹出(排队)
- queue本身没有提供迭代器
代码:
/*
* queue示例
* queue是一种容器适配器,遵循先进先出(FIFO)的原则
* queue的底层容器可以是deque、list
* 元素只能从队尾压入,从队首弹出(排队)
* queue本身没有提供迭代器
*/#include <iostream>
#include <queue>// 显示queue的函数模板
template <typename T>
void display(std::queue<T> q)
{std::cout << "[";while (!q.empty()){T elem = q.front(); // 读取队首元素std::cout << elem << " ";q.pop(); // 弹出队首元素}std::cout << "]" << std::endl;
}int main()
{std::queue<int> q;for (auto i : {1, 2, 3, 4, 5})q.push(i);display(q);std::cout << "队首元素: " << q.front() << std::endl;std::cout << "队尾元素: " << q.back() << std::endl;q.push(100); // 压入元素display(q);q.pop(); // 弹出元素q.pop();display(q);// q.clear(); // 并没有clear()方法while (!q.empty())q.pop(); // 弹出所有元素display(q);std::cout << "size: " << q.size() << std::endl;q.push(10);q.push(20);q.push(30);display(q);std::cout << "第一个元素: " << q.front() << std::endl;std::cout << "最后一个元素: " << q.back() << std::endl;q.front() = 100; // 修改队首元素q.back() = 200; // 修改队尾元素display(q);return 0;
}
11、priority_queue (优先级队列)示例
- 允许按照优先级来插入和删除元素
- 优先级最高的元素总是位于队首(最大值在队首)
- 本身没有提供迭代器
代码:
/*
* priority_queue (优先级队列)示例
* 允许按照优先级来插入和删除元素
* 优先级最高的元素总是位于队首(最大值在队首)
* 本身没有提供迭代器*/
#include <iostream>
#include <queue>// 显示priority_queue的函数模板
template <typename T>
void display(std::priority_queue<T> pq)
{std::cout << "[";while (!pq.empty()){T elem = pq.top(); // 读取优先级最高元素std::cout << elem << " ";pq.pop(); // 弹出优先级最高元素}std::cout << "]" << std::endl;
}void test1()
{std::cout << "test1 ======================" << std::endl;std::priority_queue<int> pq;for (auto i : {3,5,8,1,2,9,4,7,6})pq.push(i);display(pq);std::cout << "大小: " << pq.size() << std::endl;std::cout << "最大值: " << pq.top() << std::endl;pq.pop(); // 弹出最大值display(pq);
}int main()
{test1();return 0;
}
相关文章:

C++进阶语法——STL 标准模板库(下)(Standard Template Library)【学习笔记(七)】
文章目录 STL 代码示例1、迭代器2、算法3、array容器示例4、vector示例5、deque(double ended queue,双端数组)示例6、list(链表)容器7、set示例8、map示例9、stack 示例10、queue示例11、priority_queue (…...

力扣:求最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀,返回空字符串 示例1: 输入: strs ["flower", "flow" , "flight"] 输出: "fl" 示例2: 输入: strs ["dog","racecar","car&…...

Redis入门04-消息通知
目录 Redis中的消息通知 命令行操作 Redis中的管道 Redis中的消息通知 Redis可以用作消息队列的中间件,它提供了一种轻量级、高性能的消息传递机制,适用于实时通信、任务队列、事件处理等各种应用。以下是有关如何使用Redis作为消息队列的一些重要信…...

关于idea使用的一些操作设置
关于idea使用的一些操作设置 1. 常用的一下设置1.1 快捷键相关1.2 配置自动生成注释(类、方法等)1.3 maven项目相关1.4 常见其他的一些操作设置 2. IntelliJ IDEA 取消param注释中参数报错提示3. idea同时打开多个文件,导航栏不隐藏、自动换行…...

CLion 2023.2.2(C ++ IDE智能代码编辑器)
CLion 2023是一款跨平台C/C集成开发环境(IDE)。它为Mac用户提供了高效的编程体验,帮助程序员们在Mac平台上进行C/C开发。 CLion 2023支持多种编译器和调试器,并具有强大的代码分析和导航功能。它还为用户提供了许多便捷的工具和插…...

企业级API资产如何管理
在当今数字化时代,API已成为企业开发和创新的重要工具,如何高效地管理和调度这些资产成为了企业发展的重要课题。API资产管理的出现,为企业解决了这一难题,通过合理管理和利用API资产,企业可以更好地推动业务发展&…...

Git https方式拉的代码IDEA推送代码报错
报错信息 fatal: could not read Username for ‘https://codehub-cn-south-1.devcloud.huaweicloud.com’: No such file or directory 18:18:39.885: [recovery_pattern] git -c credential.helper -c core.quotepathfalse -c log.showSignaturefalse push --progress --porc…...

C++ capacity()用法总结
1. 容器的容量 容器的size是指它已经保存的元素的数目;而capacity则是在不分配新的内存空间的前提下它最多可以保存多少元素。capacity(),size(),reserve(),resize()这几个都是不太容易区分的函数 functionmeancapacity()获得容…...

TensorFlow2.0教程1-Eager
文章目录 张量极其操作1 张量自定义层一、网络层layer的常见操作二、实现自定义网络层三、网络层组合自动求导一、Gradient tapes二、记录控制流三、高阶梯度自定义训练(基础)一、Variables二、示例:拟合线性模型1、定义模型2.定义损失函数3.获取训练数据4.定义训练循环张…...

Redis学习系统(持续更新中)
RedisExample 课程介绍 目标是提供一个高效、可靠的学习和实践Redis的环境。我们将通过搭建Redis集群、实现缓存数据的持久化存储、制定缓存数据的淘汰策略以及同步缓存数据等步骤来深入了解和学习Redis的特性和功能。通过这个项目,你可以掌握Redis的核心概念和技…...

el-select获取id和name
一般选中节点只会返回:value绑定的数据给v-model中,要想获取id和name一并传给后端,需要如下几步: 1、给选择框添加点击事件 input"selectChangeParent" 2、v-for中多添加一个参数 index <el-select v-model"inputForm.pr…...

最简单的驱动程序
简介 在 Linux 内核中,Makefile 和 Kconfig 是两个重要的文件,它们分别承担着不同的作用。 Makefile Makefile 是一个文本文件,用于定义编译和构建内核的规则。它使用 make 工具来管理和自动化构建过程。Makefile 定义了编译器、链接器、编译选项、目标文件、源文件等信息…...

MFC String类的初始化学习
之前写过CString的用法; VC CString 编程实例图解_bcbobo21cn, cstring-CSDN博客 下面单独看一下CString的各种初始化方式; void CTest2View::OnDraw(CDC* pDC) {CTest2Doc* pDoc GetDocument();ASSERT_VALID(pDoc);// TODO: add draw code for nati…...

vue项目使用vite设置proxy代理,vite.config.js配置,解决本地跨域问题
vue3vite4项目,配置代理实现本地开发跨域问题 非同源请求,也就是协议(protocol)、端口(port)、主机(host)其中一项不相同的时候,这时候就会产生跨域 vite的proxy代理和vue-cli的proxy大致相同,需要在vite.config.js文件中配置&…...

实用-----七牛云绑定自定义域名 配置 HTTPS
实用-----七牛云绑定自定义域名 配置 HTTPS(无废话 无尿点) 1.访问SSL证书购买页面 https://portal.qiniu.com/certificate/ssl 2.购买免费证书 3.补全信息 注意: 域名直接输入 无需 www座机号随意填 区号需要搜索 下面为示例 4. 直接确认…...

【TS篇三】类、函数、for-of循环、类型推断
文章目录 一、类1.1 基本示例1.2 继承1.3 实例成员访问修饰符1.3.1 public 开放的1.3.2 private 私有的1.3.3 protected 受保护的1.3.4 readonly 只读的1.3.5 在参数中使用修饰符 1.4 属性的存(get)取(set)器1.5 静态成员 二、函数…...

Chatgpt批量改写文章网页版可多开软件-自动登录换号生成word或者TXT
Chatgpt批量改写文章网页版可多开软件介绍: 1、改写后生成docx格式文档和生成txt文档二选一。 2、支持原来docx文档里带图片的改写,改写伪原创后的docx里也带图片。 3、软件可以设置是否开启标题改写,可以自定义标题改写指令。 4、可以设置…...

Modelsim 使用教程(4)—— Working With Multiple Libraries
一、概述 在文中,我们将练习使用多个库。在实际的项目开发过程中,我们可能有多个库来组织设计,从第三方源代码访问IP,或者在仿真之间共享公共部分。我们将通过创建一个包含计数器设计单元的资源库来开始本文。接下来,我…...

【重要】浏览器输入地址提示【您的连接不是私密连接】解决方法
在配置 kubernetes-dashboard 时,出现您的连接不是私密连接,这种情况下,点开高级没有进一步的操作按钮,这是由于我们的证书无效导致浏览器自身防护拦截,为了接解决这个办法我们可以使用命令 thisisunsafe 强制信任该网…...

ESP-07S烧写固件记录
一,固件版本。 下面是官方默认AT指令版本,ESP-07S 的flash大小是4MB。 AT固件汇总 | 安信可科技 (ai-thinker.com) 二,烧录工具。 开发工具清单 | 安信可科技 (ai-thinker.com) 三,下载工具及连线。 使用USB转串口工具。 四&am…...

网络编程中关于UDP套接字的一些知识点
关于UDP的介绍: UDP(User Datagram Protocol,用户数据报协议)是一种面向无连接的、不可靠的传输协议,它在网络编程中也起着重要的作用。 1. 低延迟:相比于TCP,UDP没有建立连接和拥塞控制的开销…...

淘宝商品评论API接口(评论内容|日期|买家昵称|追评内容|评论图片|评论视频..)
淘宝商品评论API接口是淘宝开放平台提供的一种API接口,可以帮助开发者获取淘宝平台上的商品评论数据。 要使用淘宝商品评论API接口,需要进行以下步骤: 注册淘宝开放平台账号,创建应用并获取App Key和App Secret等信息。确定需要…...

计算机网络 第五章传输层
文章目录 1 传输层的功能2 传输层两种协议:UDP和TCP3 端口和端口号4 UDP数据报特点和首部格式5 UDP校验6 TCP协议的特点7 TCP报文段首部格式8 TCP连接:三次握手建立连接9 TCP连接:四次挥手释放连接10 TCP可靠传输11 TCP流量控制12 TCP拥塞控制…...

cartographer,ros,路径规划近两年的工作笔记
马上转入cartographer的去ros移植了,随便记录一下研究cartographer和ros这些天来的摸鱼笔记吧虽然很多人对用ros做产品嗤之以鼻,但是我个人是不排斥的,对代码能力有限的人群来说这是产品化最快的方式! 敝帚自珍~~~继续加油~~~ 建图总结 odom 尤其是转弯的时候,存在累积误…...

react 生命周期讲解
当涉及到React组件的创建、更新和销毁过程时,React的生命周期方法起到了至关重要的作用。正确地理解和使用这些生命周期方法可以帮助我们在不同的阶段执行特定的操作,从而实现更好的组件控制和优化。 1. 挂载阶段(Mounting) 在组…...

什么是TCY油封?
机械由无数组件协同工作以确保平稳运行,其中一种不可或缺的部件是油封,特别是TCY油封。本文旨在阐明TCY油封的应用、其重要性以及它们如何提高机械的整体效率。 TCY油封主要用于轴密封。轴是一种旋转机器元件,横截面通常为圆形,用…...

【Vue.js】使用Element入门搭建登入注册界面axios中GET请求与POST请求跨域问题
一,ElementUI是什么? Element UI 是一个基于 Vue.js 的桌面端组件库,它提供了一套丰富的 UI 组件,用于构建用户界面。Element UI 的目标是提供简洁、易用、美观的组件,同时保持灵活性和可定制性 二,Element…...

Apache Hive
目录 数据仓库(DW) SQL语法分类 Hive 和Hadoop之间的关系(底层是Hadoop Hive将SQL转换为MapReduce) 为什么使用Hive 使用Hadoop MapReduce直接处理数据所面临的问题 使用Hive处理数据的好处 对Hive的理解 A…...

[idea]关于idea开发乱码的配置
在JAVA开发中,一般统一设置为UTF-8的编码,包括但不限于开发工具、日志架构、虚拟机、文件编码等。常见配置如下: 1、IDEA工具 在idea64.exe.vmoptions、idea.exe.vmoptions中添加: -Dfile.encodingUTF-8 2、JAVA 运行在window…...

比较一个结构分割平面的两种方式
在8*8的范围内,差值结构4a81把空间分割成4个部分, 31 31 31 27 27 31 31 31 31 31 31 27 27 31 31 31 9 9 9 1 1 9 9 9 9 9 9 1 1 9 9 9 9 9 9 1 1 9 9 9 9 9 9 1 1 9 9 9 31 31 31 27 27 31 31 …...