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对于多线程 ...
随机推荐
- STM32 Keil 软件仿真设置
设置 Dialog.DLL 分别为:DARMSTM.DLL和TARMSTM.DLL, Parameter 均为:-pSTM32F103RC,用于设置支持芯片的软硬件仿真
- 王艳 201771010127《面向对象程序设计(java)》第二周学习总结
王艳 201771010127<面向对象程序设计(java)>第二周学习总结 第一部分:理论知识学习部分 3.1:基本概念. 1)标识符:标识符由字母.数字.美元符号以及下划线组成.且第 ...
- CF918C The Monster
题目链接:http://codeforces.com/contest/918/problem/C 知识点: 贪心 解题思路: 枚举起点(当起点就是\(')'\)时直接跳过)并在此基础上遍历字符串,用一 ...
- vue脚手架3.0的安装与使用
一.安装 1.先检查是否有安装vue (vue-cli3需要node大于等于8.9版本) //vue -V 2.如果没安装跳过.安装有3.0以下的版本就的先卸载掉以前的版本 npm uninstal ...
- 允许远程用户登录访问mysql
方法1.本地登入mysql,更改 “mysql” 数据库里的 “user” 表里的 “host” 项,将”localhost”改为”%” mysql -u root -proot use mysql; ...
- C#中操作JSON
引入支持JSON操作的库,比如LitJSON: 引入之后就可以解析JSON了. 写一个JSON文本 读取这个JSON文本: 解析JSON数据最佳实践--使用泛型,将泛型类型指定成自己定义的类型,直接获 ...
- 一文带你学会基于SpringAop实现操作日志的记录
前言 大家好,这里是经典鸡翅,今天给大家带来一篇基于SpringAop实现的操作日志记录的解决的方案.大家可能会说,切,操作日志记录这么简单的东西,老生常谈了.不! 网上的操作日志一般就是记录操作人, ...
- python之robotframework+ride测试框架
一.robotframework简介 Robot Framework是一款python编写的功能自动化测试框架.具备良好的可扩展性,支持关键字驱动,可以同时测试多种类型的客户端或者接口,可以进行分布式 ...
- 【JavaScript数据结构系列】04-优先队列PriorityQueue
[JavaScript数据结构系列]04-优先队列PriorityQueue 码路工人 CoderMonkey 转载请注明作者与出处 ## 1. 认识优先级队列 经典的案例场景: 登机时经济舱的普通队 ...
- JavaScript之倔强的字符串
关于倔强的JavaScript字符串:不可以被修改 我们是字符串 我们的口号是:你可以消灭我,但是你不能改变我 JavaScript字符串是不可改变的,当真是这样的吗? 让我们来试验一下. var n ...