c++ stl(标准模板库)

1. 引言

STL(标准模板库),从广义上分为:容器,算法,迭代器,容器和算法之间通过迭代器进行无缝连接。

在 c++ 标准种,STL被组织成以下13个头文件:

<algorithm>
<deque>
<functional>
<iterator>
<vector>
<list>
<map>
<memory>
<numeric>
<queue>
<stack>
<utility>

容器总体分为两种:

  • 序列式容器:容器的元素的位置是由进入容器的时机和地点来决定的。
  • 关联式容器:容器已经有规则,进入容器的元素的位置不是由进入容器的时机和地点来决定的。

容器是可以嵌套使用的,也就是容器可以装容器。

迭代器起到指针的作用,对指针的操作基本都可以对迭代器操作。实际上,迭代器式一个类,这个类封装一个指针。

算法,通俗的解释,就是通过优先步骤,解决一个问题。

下面给出一个简单的示例,通过这个示例,我们可以很直观的看到容器、迭代器、算法之间的密不可分的关系:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

void printVector(int v) 
{
	cout << v << " ";
}

int main()
{
	//容器
	vector<int> v;
	v.push_back(10);
	v.push_back(20);
	v.push_back(30);
	v.push_back(40);

	//迭代器
	vector<int>::iterator pBegin = v.begin();
	vector<int>::iterator pEnd = v.end();

	//算法
	for_each(pBegin, pEnd, printVector);

	return 0;
}

2. string 容器

2.1 简要说明

  • string是一个类,内部封装了char*,是一个char*型的容器。
  • 封装了很多成员方法。
  • 自动管理char*内存,不用主动定义字符串的长度。

string 和 char* 可以互相转换:

//string 转 char*
string str = "itcast";
const char* cstr = str.c_str();

//char* 转 string
const char* s = "itcast";
string sstr(s);

2.2 string 常用 API

(1)构造函数

(2)赋值

  • assign()
  • =

(3)取值

  • []
  • at()

两者的区别:[]方式如果访问越界,直接挂了,at()方式如果访问越界,抛出异常。

(4)拼接

  • +
  • +=
  • str.append()

(5)查找和替换

  • find():查找第一次出现的位置
  • rfind():查找最后一次出现的位置
  • replace():把给定一段区间替换成别的字符串

(6)比较

  • compare()

(7)子串

  • substr()

(8)插入和删除

  • insert()
  • erase()

3. vector 容器

3.1 简要说明

  • vector 容器是动态数组。
  • 单口容器,即从尾部插入(push_back)和删除(pop_back)的效率更高。从其他位置插入删除会引起其他元素的移动,从而效率低下。
  • 提供insert()来从指定位置插入。
  • begin()end()标识指向第一个元素和最后一个元素的下一个位置,用rbegin()rend()标识指向最后一个元素和第一个元素的上一个位置。
  • 支持随机访问。

随机访问的概念:迭代器支持加减一个数的操作,比如v.begin() + 2

3.2 vector 常用 API

(1)构造函数

(2)赋值

  • assign()
  • =
  • swap()

(3)大小

  • size()
  • empty()
  • resize():重新指定容器的长度,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
  • capacity()
  • reserve():预留容器的容量,但不初始化,元素不可访问。

(4)取值

  • at():若超出范围,抛异常
  • []:若超出范围,不抛异常,直接挂
  • front():返回第一个元素
  • back():返回最后一个元素

(5)插入和删除

  • push_back()
  • insert()
  • pop_back()
  • emplace()
  • emplace_back()
  • erase()

c++ 11中,针对顺序容器(如vector、deque、list),新标准引入了三个新成员,emplace_front()、emplace_back()、emplace(),分别对应push_front()、push_back()、insert(),允许我们将元素放置在容器头部、容器尾部或一个指定位置之前,但emplace_front()、emplace_back()、emplace()的效率更高。

(6)用swap()缩减容量

int main()
{
	vector<int> vec;
	for (int i = 0; i < 1000; i++) {
		vec.push_back(i);
	}
	cout << vec.size() << endl;//1000
	cout << vec.capacity() << endl;//1066
	vec.resize(10);
	cout << vec.size() << endl;//10
	cout << vec.capacity() << endl;//1066

	vector<int> v(vec);
	cout << v.size() << endl;//10
	cout << v.capacity() << endl;//10

	//结论:resize只影响vector的元素的数量,但不会影响vector的容量,但vector的拷贝构造函数会使容量等于元素数量

	//因此可以用匿名对象 + swap来缩小容量,swap的功能是交换两个对象
	vector<int>(vec).swap(vec);
	cout << v.size() << endl;//10
	cout << v.capacity() << endl;//10
	
	return 0;
}

4. deque 容器

4.1 简要说明

  • 双端数组,可以从头部和尾部进行插入和删除,push_back(), pop_back(), push_front(), pop_front()
  • begin()返回一个迭代器,指向第一个元素,end()返回一个迭代器,指向最后一个元素的下一个位置,front()返回第一个元素,back()返回最后一个元素。
  • insert()可以指定位置插入,但会导致元素移动,降低效率。
  • 可随机存取,效率高。

4.2 deque 常用 API

(1)构造函数

(2)赋值

  • assign()
  • =
  • swap()

(3)大小操作

  • size()
  • empty()
  • resize()

(4)插入和删除

  • push_back()
  • push_front()
  • pop_back()
  • pop_front()
  • insert()
  • erase()
  • emplace()
  • emplace_back()
  • emplace_front()

(5)存取

  • at()
  • []
  • front()
  • back()

5. stack 容器

5.1 简要说明

  • 先进后出,通过压栈push()从栈顶增加元素,通过出栈pop()从栈顶删除元素。
  • 不能遍历(不提供迭代器),不支持随机存取。只能通过top()访问栈顶元素。

5.2 stack 常用 API

(1)构造函数

(2)插入和删除

  • push()
  • pop()

(3)取值

  • top()

6. queue 容器

6.1 简要说明

  • 先进先出,通过入队push()从队尾增加元素,通过出队pop()从队头删除元素。
  • front()返回队头元素,back()返回队尾元素。
  • 不能进行遍历(不提供迭代器),不支持随机访问。

6.2 queue 常用 API

(1)构造函数

(2)存取、插入、删除

  • push()
  • pop()
  • back()
  • front()

(3)赋值

  • =

(4)大小

  • empty()
  • size()

7. list 容器

7.1 简要说明

  • 双向链表,每个结点由data、prev指针和next指针构成,头节点的prev指针指向null,尾节点的next指针指向null。
  • 通过push_back()pop_back()从尾部添加和删除元素,通过push_front()pop_front()从头部添加和删除元素。通过insert()从给定位置之前插入元素。
  • begin()返回指向链表头的迭代器,end()返回指向链表尾的迭代器。
  • 不支持随机访问,只能迭代器++或–。

7.2 list 常用 API

(1)构造函数

(2)插入和删除

  • push_back()
  • pop_back()
  • push_front()
  • pop_front()
  • insert()
  • clear()
  • erase()
  • remove(elem):删除容器中所有与值elem匹配的元素。

(3)大小

  • size()
  • empty()
  • resize()

(4)赋值

  • assign()
  • =
  • swap()

(5)取值

  • front()
  • back()

(6)翻转链表

  • reverse()
  • sort()

这是list中自带的reverse和sort,不是算法中的reverse和sort。算法中的只支持可随机访问的容器。

8. set/multiset 容器

8.1 简要说明

  • set/multiset的特性是所有元素会根据元素的值自动进行排序,默认升序排序。set/multiset是以红黑树尾底层机制,其查找效率非常好。set容器中不允许重复元素,multiset允许重复元素。
  • 通过insert()插入数据,自动排序。
  • 可以遍历(提供迭代器),不支持随机存取。
  • set/multiset不能通过迭代器改变元素的值,因此这样会打破set/multiset的排序规则。

8.2 set/multiset 常用 API

(1)构造函数

(2)赋值

  • =
  • swap()

(3)大小

  • size()
  • empty()

(4)插入和删除

  • insert()
  • clear()
  • erase()

(5)查找

  • find(key):返回迭代器
  • lower_bound(keyElem):返回第一个key>=keyElem元素的迭代器
  • upper_bound(keyElem):返回第一个key>keyElem元素的迭代器
  • equal_range(keyElem):返回lower_bound和upper_bound的两个迭代器,数据结构是pair(iterator, iterator)。

8.3 自定义set/multiset的排序规则

我们可以使用仿函数来定义,仿函数是一个类,在这个类中我们重载()运算符

//仿函数
class mycompare { //用struct定义也可以
public:
	bool operator()(const int& v1, const int& v2) const {
		return v1 > v2;
	}
};

int main()
{
	set<int, mycompare> s;
	s.insert(1);
	s.insert(2);
	s.insert(-1);
	s.insert(5);
	for (auto it = s.begin(); it != s.end(); it++) {
		cout << *it << endl;
	}
	return 0;
}

9. pair(对组)容器

9.1 简要说明

  • pair 将一对值组合成一个值,这一对值可以具有不同的数据类型,两个值可以分别用pair的两个共有函数first()second()访问。
  • 可以通过pair的构造函数创建队组,也可以通过make_pair()函数创建队组。

10. map/multimap 容器

10.1 简要说明

  • map相对于set,具有key 和 value,所有元素根据key自动排序。pair的第一元素被称为键值,第二元素被称为实值。map也是以红黑树为底层实现机制。
  • map的元素是pair
  • key不能修改,value可以修改

10.2 map/multimap 常用 API

(1)构造函数

(2)赋值

  • =
  • swap()

(3)大小

  • size()
  • empty()

(4)插入和删除

  • insert(pair<int,int>(1,2))
  • insert(make_pair(1,2))
  • emplace(1,2)
  • clear()
  • erase()

(5)查找

  • find(key):返回迭代器
  • lower_bound(keyElem):返回第一个key>=keyElem元素的迭代器
  • upper_bound(keyElem):返回第一个key>keyElem元素的迭代器
  • equal_range(keyElem):返回lower_bound和upper_bound的两个迭代器,数据结构是pair(iterator, iterator)。

11. unordered_set/unordered_multiset 容器

11.1 简要说明

  • 无序 set/multiset 容器,和 set/multiset 容器很像,唯一的区别就在于 set 容器会自行对存储的数据进行排序,而 unordered_set 容器不会。
  • 不再以键值对的形式存储数据,而是直接存储数据的值。
  • 容器内部存储的各个元素的值不能被修改。
  • 不会对内部存储的数据进行排序,因为底层采用哈希表结构存储数据。

unordered_set 容器的类模板定义如下:

template < class Key,            //容器中存储元素的类型
           class Hash = hash<Key>,    //确定元素存储位置所用的哈希函数
           class Pred = equal_to<Key>,   //判断各个元素是否相等所用的函数
           class Alloc = allocator<Key>   //指定分配器对象的类型
           > class unordered_set;

可以看到,以上 4 个参数中,只有第一个参数没有默认值,这意味着如果我们想创建一个 unordered_set 容器,至少需要手动传递 1 个参数。事实上,在 99% 的实际场景中最多只需要使用前 3 个参数(各自含义如表 1 所示),最后一个参数保持默认值即可。

在这里插入图片描述

12. unordered_map/unordered_multimap 容器

12.1 简要说明

  • 无序 map/multimap 容器,和 map/multimap 容器很像,唯一的区别就在于,map 容器中存储的数据是有序的,而 unordered_map 容器中是无序的。
  • 底层采用的是哈希表存储结构,该结构本身不具有对数据的排序功能,所以此容器内部不会自行对存储的键值对进行排序。

unordered_map 容器模板的定义如下所示:

template < class Key,                        //键值对中键的类型
           class T,                          //键值对中值的类型
           class Hash = hash<Key>,           //容器内部存储键值对所用的哈希函数
           class Pred = equal_to<Key>,       //判断各个键值对键相同的规则
           class Alloc = allocator< pair<const Key,T> >  // 指定分配器对象的类型
           > class unordered_map;

以上 5 个参数中,必须显式给前 2 个参数传值,并且除特殊情况外,最多只需要使用前 4 个参数,各自的含义和功能如表 1 所示。

在这里插入图片描述

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值