STL容器操作
1. 数组
int a[] = {1, 2, 3, 4, 5, 5};
2. Vector
构造函数
* vector<datatype> a; //empty vector
* vector<datatype> b (no of elements, value of each element); //fixed number of elements with default value
* vector<datatype> c (starting iterator/pointer,ending iterator/pointer); //inserting elements from other data structures
* vector<datatype> d (name of vector to be copied);
* vector<vector<datatype> > matrix(no of rows,vector<datatype>(no of coloumn,default value)) //Declaring a 2D array
vector array{1,2,3,4};
注意:
vector<datatype> v[10];, following declaration isn't a vector with 10 elements but an array of size ten having vector elements.
methods:
- at(index) # 等同于 "[]" operator
- clear()
- push_back(item)
- pop_back()
- front()
- back()
- empty()
- size()
- resize(n)
3. List
methods:
- front()
- back()
- begin()
- end()
- rbegin()
- rend()
- empty()
- size()
- resize()
- max_size()
- push_back()
- push_front()
- insert() # 任意位置插入
- pop_back()
- pop_front()
- clear()
- erase() # 删除一个元素或一个区域的元素(两个重载)
- remove() # 删除链表中匹配值的元素(匹配元素全部删除)
- remove_if() # 删除条件满足的元素(遍历一次链表),参数为自定义的回调函数
- reverse()
- sort()
- merge()
- splice()
- swap()
- unique()
3.1. std::forward_list
std::forward_list 是一个列表容器,使用方法和 std::list 基本类似,因此我们就不花费篇幅进行介绍了。
需要知道的是,和 std::list 的双向链表的实现不同,std::forward_list 使用单向链表进行实现, 提供了 O(1) 复杂度的元素插入,不支持快速随机访问(这也是链表的特点), 也是标准库容器中唯一一个不提供 size() 方法的容器。当不需要双向迭代时,具有比 std::list 更高的空间利用率。
4. Tuple
构造函数
* tuple <char, int, float> gk;
* tuple <int,char,float> tup1(20,'g',17.5);
* tuple <char, int, float> gk2 = make_tuple('a', 10, 15.5);
int len_tuple = tuple_size<decltype(gk)>::value;
tie(i_val,ch_val,f_val) = tup1;
method:
- get() # get<0>(gk)
- make_tuple()
- tuple_size
- swap()
- tie()
- tuple_cat()
std::get 除了使用常量获取元组对象外,C++14 增加了使用类型来获取元组中的对象:
std::tuple<std::string, double, double, int> t("123", 4.5, 6.7, 8);
std::cout << std::get<std::string>(t) << std::endl;
std::cout << std::get<double>(t) << std::endl; // 非法, 引发编译期错误
std::cout << std::get<3>(t) << std::endl;
4.1. 运行期索引
如果你仔细思考一下可能就会发现上面代码的问题,std::get<> 依赖一个编译期的常量,所以下面的方式是不合法的:
int index = 1;
std::get<index>(t);
那么要怎么处理?答案是,使用 std::variant<>(C++ 17 引入),提供给 variant<> 的类型模板参数 可以让一个 variant<> 从而容纳提供的几种类型的变量(在其他语言,例如 Python/JavaScript 等,表现为动态类型):
#include <variant>
template <size_t n, typename... T>
constexpr std::variant<T...> _tuple_index(const std::tuple<T...>& tpl, size_t i) {
if constexpr (n >= sizeof...(T))
throw std::out_of_range("越界.");
if (i == n)
return std::variant<T...>{ std::in_place_index<n>, std::get<n>(tpl) };
return _tuple_index<(n < sizeof...(T)-1 ? n+1 : 0)>(tpl, i);
}
template <typename... T>
constexpr std::variant<T...> tuple_index(const std::tuple<T...>& tpl, size_t i) {
return _tuple_index<0>(tpl, i);
}
template <typename T0, typename ... Ts>
std::ostream & operator<< (std::ostream & s, std::variant<T0, Ts...> const & v) {
std::visit([&](auto && x){ s << x;}, v);
return s;
}
这样我们就能:
int i = 1;
std::cout << tuple_index(t, i) << std::endl;
4.2. 元组合并
还有一个常见的需求就是合并两个元组,这可以通过 std::tuple_cat 来实现:
auto new_tuple = std::tuple_cat(get_student(1), std::move(t));
4.3. 元祖遍历
我们刚才介绍了如何在运行期通过非常数索引一个 tuple 那么遍历就变得简单了, 首先我们需要知道一个元组的长度,可以:
template <typename T>
auto tuple_len(T &tpl) {
return std::tuple_size<T>::value;
}
这样就能够对元组进行迭代了:
// 迭代
for(int i = 0; i != tuple_len(new_tuple); ++i)
// 运行期索引
std::cout << tuple_index(i, new_tuple) << std::endl;
5. Pair
构造方法:
* pair <data_type1, data_type2> Pair_name (value1, value2);
* pair <data_type1, data_type2> g1; //default
* pair <data_type1, data_type2> g2(1, 'a'); //initialized, different data type
* pair <data_type1, data_type2> g3(1, 10); //initialized, same data type
* pair <data_type1, data_type2> g4(g3); //copy of g3
Pair<string, int> xxx = make_pair(key, value);
methods:
- operators(=, ==, !=, >=, <=)
- swap()
6. Sets / Multiset
二者的区别:
Set集合中一个值只能出现一次,而Multiset中一个值可以出现多次。
int a[] = {1, 2, 3, 4, 5, 5};
set<int> s2 (a, a + 6); // s2 = {1, 2, 3, 4, 5}
set<int> s4 (s3.begin(), s3.end());
method:
- insert()
- erase()
- begin()
- end()
- clear()
- count()
- empty()
- find()
- size()
- contains (C++20) 检查容器是否含有带特定键的元素
6.1. std::unordered_set / std::unordered_multiset
7. Map / Multimap
std::map<int, string> dict = {
{0, "ahts"},
{1, "1234"}
};
method:
map<char, int> map_b(map_a.begin(), map_a.end());
map_a.insert(pair<char, int>('a', 502));
map_a['a'] = 10;
cout << map_a['b'];
cout << map_a.at('b');
map_a.find('b');
map_a.erase('b');
7.1. std::unordered_map / std::unordered_multimap
8. 无序容器
我们已经熟知了传统 C++ 中的有序容器 std::map / std::set ,这些元素内部通过 红黑树 进行实现, 插入和搜索的平均复杂度均为 O(log(size)) 。在插入元素时候,会根据 < 操作符比较元素大小并判断元素是否相同, 并选择合适的位置插入到容器中。当对这个容器中的元素进行遍历时,输出结果会按照 < 操作符的顺序来逐个遍历。
而无序容器中的元素是不进行排序的,内部通过哈希表实现,插入和搜索元素的平均复杂度为 O(constant) , 在不关心容器内部元素顺序时,能够获得显著的性能提升。
C++11 引入了两组无序容器: std::unordered_map / std::unordered_multimap 和 std::unordered_set / std::unordered_multiset 。
它们的用法和原有的 std::map/std::multimap/std::set/set::multiset 基本类似, 由于这些容器我们已经很熟悉了,便不再举例了。
9. Queue / PriorityQueue
methods:
- push()
- pop()
- front()
- empty()
- size()
A priority queue is a container that provides constant time extraction of the largest element.
In a priority queue, an element with high priority is served before an element with low priority.
All insertion / deletion operations takes place in Logarithmic time.
10. 10. Stack
methods:
- push()
- pop()
- top() # Returns a reference to the top most element of the stack
- empty()
- size()
11. 11. Bitsets
https://github.com/kjsce-codecell/standard-library-in-x/blob/master/cpp/containers/bitsets.md
12. 12. std::array
看到这个容器的时候肯定会出现这样的问题:
为什么要引入 std::array 而不是直接使用 std::vector
与 std::vector 不同,std::array 对象的大小是固定的,如果容器大小是固定的,那么可以优先考虑使用 std::array 容器。
另外由于 std::vector 是自动扩容的,当存入大量的数据后,并且对容器进行了删除操作, 容器并不会自动归还被删除元素相应的内存,这时候就需要手动运行 shrink_to_fit() 释放这部分内存。
已经有了传统数组,为什么要用 std::array
使用 std::array 能够让代码变得更加“现代化”,而且封装了一些操作函数,比如获取数组大小以及检查是否非空,同时还能够友好的使用标准库中的容器算法,比如 std::sort。
12.1. 12.1. std::array 的使用
std::array<int, 4> arr = {1, 2, 3, 4};
arr.empty(); // 检查容器是否为空
arr.size(); // 返回容纳的元素数
// 迭代器支持
for (auto &i : arr)
{
// ...
}
// 用 lambda 表达式排序
std::sort(arr.begin(), arr.end(), [](int a, int b) {
return b < a;
});
// 数组大小参数必须是常量表达式
constexpr int len = 4;
std::array<int, len> arr = {1, 2, 3, 4};
// 非法,不同于 C 风格数组,std::array 不会自动退化成 T*
// int *arr_p = arr;
12.2. 12.2. 兼容 C 风格的接口
void foo(int *p, int len) {
return;
}
std::array<int, 4> arr = {1,2,3,4};
// C 风格接口传参
// foo(arr, arr.size()); // 非法, 无法隐式转换
foo(&arr[0], arr.size());
foo(arr.data(), arr.size());
// 使用 `std::sort`
std::sort(arr.begin(), arr.end());
STL容器操作的更多相关文章
- STL容器能力一览表和各个容器操作函数异常保证
STL容器能力一览表 Vector Deque List Set Multiset map Multimap 典型内部 结构 dynamic array Array of arrays Doubly ...
- 【C++】STL,vector容器操作
C++内置的数组支持容器的机制,但是它不支持容器抽象的语义.要解决此问题我们自己实现这样的类.在标准C++中,用容器向量(vector)实现.容器向量也是一个类模板.标准库vector类型使用需要的头 ...
- c++ stl容器set成员函数介绍及set集合插入,遍历等用法举例
c++ stl集合set介绍 c++ stl集合(Set)是一种包含已排序对象的关联容器.set/multiset会根据待定的排序准则,自动将元素排序.两者不同在于前者不允许元素重复,而后者允许. 1 ...
- STL容器删除元素的陷阱
今天看Scott Meyers大师的stl的用法,看到了我前段时间犯的一个错误,发现我写的代码和他提到错误代码几乎一模一样,有关stl容器删除元素的问题,错误的代码如下:std::vector< ...
- STL容器的适用情况
转自http://hsw625728.blog.163.com/blog/static/3957072820091116114655254/ ly; mso-default-props:yes; m ...
- STL容器的遍历删除
STL容器的遍历删除 今天在对截包程序的HashTable中加入计时机制时,碰到这个问题.对hash_map中的每个项加入时间后,用查询函数遍历hash_map,以删除掉那些在表存留时间比某个阈值长的 ...
- STL容器与配接器
STL容器包括顺序容器.关联容器.无序关联容器 STL配接器包括容器配接器.函数配接器 顺序容器: vector 行为类似于数组,但可以根据要求 ...
- STL容器的本质
http://blog.sina.com.cn/s/blog_4d3a41f40100eof0.html 最近在学习unordered_map里面的散列函数和相等函数怎么写.学习过程中看到了一个好帖子 ...
- STL容器是否是线程安全的
转载http://blog.csdn.net/zdl1016/article/details/5941330 STL的线程安全. 说一些关于stl容器的线程安全相关的话题. 一般说来,stl对于多线程 ...
随机推荐
- 最小生成树 状压+prim hdu2489
Minimal Ratio TreeTime Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
- LightOJ1030 Discovering Gold
题目链接:https://vjudge.net/problem/LightOJ-1030 知识点: 概率与期望 解题思路: 设某一个点 \(i\) 能到达的点的个数为 \(x\),其上有金 \(g\) ...
- JavaScript编程入门
写在前面: 不管容易还是简单 总要尝试才知道答案 1.JavaScript初探 JavaScript:轻量级脚本语言,是可插入HTML页面的编程代码. 将JavaScript插入HTML页 ...
- 关于mobileSelect.js日期数据获取封装,动态时间,封装
传入起始年份和起始月份 得到 插件的标准格式放到 效果 let getAllDatas = (stime, etime) => { //接收传进来的参数月份 var data_M = etime ...
- window端口被占用
一.问题描述 今天一来公司,在IntelliJ IDEA 中启动Tomcat服务器时就出现了如下图所示的错误: 错误: 代理抛出异常错误: java.rmi.server.ExportExceptio ...
- 使用records库操作SQL并且查询MySQL数据库
获取数据库 db = records.Database('mysql://root:xxxx@47.106.151.165/web_table?charset=utf8')注释:xxxx为数据密码 执 ...
- & vue项目中的rem适配
有个朋友问我在vue项目怎么做rem适配,我工作中都是用的dva,但是我感觉道理都是一样的,换汤不换药.配完就顺手写下来吧! 需要安装两个插件库 lib-flexible和px2rem-loader ...
- 学习Pytorch遇到的一些问题(一)
基本介绍 这周开始学习深度学习的部分知识,参考的书是<动手学深度学习>(PyTorch版),在操作过程中遇到一些小问题,记录一下问题和解决办法. PyTorch下载过慢 安装步骤 PyTo ...
- 关于hexo中plugins博客配置对无法生成index.html文件的影响
用hexo搭建的博客网站在访问时出现403错误,经调查后发现是public文件夹下的index.html文件丢失. 在csdn上搜了一下发现大家都是查看是否有一下hexo的插件未安装,将未安装插件安装 ...
- Chisel3 - model - Builder
https://mp.weixin.qq.com/s/THqyhoLbbuXXAtdQXRQDdA 介绍构建硬件模型的Builder. 1. DynamicContext 动态上下文 ...