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对于多线程 ...
随机推荐
- python函数总结,你值得拥有
目录 函数总结 函数定义与结构 函数名的使用 函数的参数 名称空间与作用域 名称空间 作用域 函数嵌套 内置函数(globals( ),locals( )) global+nonlocal 可迭代对象 ...
- mysql 一台服务器中装两个mysql
个人经验: 服务器中已有mysql5.0 现要安装mysql5.5 下载安装包,安装后,mysql5.5中没有my.ini文件,就在我自己的电脑上复制了mysql5.5的my.ini文件进去. 1.在 ...
- React Native 架构演进
写在前面 上一篇(React Native 架构一览)从设计.线程模型等方面介绍了 React Native 的现有架构,本篇将分析这种架构的局限性,以及 React Native 正在进行的架构升级 ...
- SSE系列内置函数中的shuffle函数
SSE 系列内置函数中的 shuffle 函数 邮箱: quarrying@qq.com 博客: http://www.cnblogs.com/quarryman/ 发布时间: 2017年04月18日 ...
- C#中的out关键字
在一个方法里面使用out关键字的时候这个方法中作为out关键字之后的参数会被返回出去:调用这个方法的时候需要先有一个变量来承接这个传递出来.已经被该方法改动过的参数,并且要记得传实参的时候前面带上ou ...
- NOIP 2017 P3959 宝藏 (状态压缩DP板子)
洛谷题目传送门!! 题目的N这么小,当然是选择用状压DP啦! 等等,我好像不会状缩.... 首先,我们当然是要写状态转移方程了!! 那么,如果我们设 f[s] 状态s下,所要的最小花费,那么很显 ...
- 校园网络 luogu P2812 (又是强联通)
题目传送门!(luogu) 首先考虑问题一 不难想到,如果有一个学校作为终端机,那么跟其处于同一个强联通中的所有学校就可以不用作为终端机了. 那么,问题一也就迎刃而解了:找到所有入度为0的缩点.因为这 ...
- 读Pyqt4教程,带你入门Pyqt4 _013
你是否曾经看着应用程序并思考特定的GUI项是如何产生的?大概每位程序员都这样过.然后你能看到你喜欢的GUI库提供的一系列窗口组件,但是你无法找到它.工具包通常仅仅提供最常用的窗口组件,比如按钮.文本组 ...
- Java IO(五)字节流 FileInputStream 和 FileOutputStream
Java IO(五)字节流 FileInputStream 和 FileOutputStream 一.介绍 字节流 InputStream 和 OutputStream 是字节输入流和字节输出流的超类 ...
- 五、Spring Web应用程序构建
内容 映射请求到Spring控制器 透明地绑定表单参数 校验表单提交 关键词 模型-视图-控制器(Model-View-Controller,MVC) 处理器映射(handle mapping) 视图 ...