STL容器用法详解及注解(持续更新)

写在前面

以下摘录自wiki

STL又称标准模板库,是一个c++软件库,其中包含4个组件,分别为:

  • 算法
  • 容器
  • 函数
  • 迭代器

STL将“在数据上的操作”与“要执行操作的数据分开”,分别以如下概念指代:

  • 容器:包含、放置数据的地方。
  • 迭代器: 在容器中指出一个位置、或成对使用以划定一个区域,用来限定操作所涉及到的数据范围。
  • 算法: 要执行的操作。

总而言之,STL在编程的方方面面都有着巨大的作用,接下来将介绍常用的STL以及用法。

容器

Vector向量容器

Vector向量容器可在尾端插入或者删除元素,可动态调整所占用的内存空间,可以将其看作是以顺序结构实现的线性表。vector可以保存任意类型的变量,包括用户自定义的数据类型。

包含头文件

#include <vector>

创建

vector<T> vec ;

增加或者删除元素

  • vec.push_back(elem) –增加元素到vector容器的尾端
  • vec.pop_back(elem) –删除尾端元素
  • vec.insert(it,elem) –在迭代器it指向的元素前插入某一元素
  • vec.insert(it,n,elem) –在迭代器it指向的元素前插入n个元素
  • vec.erase(it) –删除迭代器it指向的元素
  • vec.erase(begin_it,end_it) –删除区间 [begin_it,end_it) 的元素
  • vec.clear() –清空全部元素

访问元素

  • vec[i] –访问索引值为i的元素
  • vec.front() –返回vec第一个元素
  • vec.back() –返回vec最后一个元素

获取当前长度或者当前容量

  • vec.size() –返回vec当前的长度
  • vec.empty() –若为空返回true否则为false

迭代器

  • vector<T>::iterator it –创建一个T数据类型的正向迭代器it
  • Vector<T>::reverse_iterator it –创建一个T数据类型的反向迭代器it

使用举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <iostream>
#include <vector>

//STL组件属于std名称空间,以下不再赘述
using namespace std ;

int main(){
cout << "enter the number of element:" << endl ;
int num ;
cin >> num ;
if ( num == 0 ){
cout << "please enter again" << endl ;
cin >> num ;
}

//创建一个数据类型为 int 的 vector 容器 vec
vector<int> vec ;
for ( int i = 0 ; i < num ; i ++ ){
cout << "input: " ;
int number ;
cin >> number ;
//将元素添加至表尾
vec.push_back(number) ;
}

//创建一个正向迭代器 it
vector<int>::iterator it ;
//创建一个反向迭代器 rit
vector<int>::reverse_iterator rit ;
cout << endl << "output:" << endl ;
//正向输出
cout << "in order: " << endl ;
for ( it = vec.begin() ; it != vec.end() ; it ++ ){
cout << *it << " " ;
}
cout << endl ;
//反向输出
cout << "reverse order: " << endl ;
for ( rit = vec.rbegin() ; rit != vec.rend() ; rit ++ ){
cout << *rit << " " ;
}
cout << endl << endl ;

//插入操作
cout << "insert:(position , element)" << endl ;
int pos , element ;
cin >> pos >> element ;
if ( pos < 0 || pos > vec.size() ){
cout << "please enter position again" << endl ;
cin >> pos ;
}
vec.insert(vec.begin() + pos , element) ;
cout << "there are *" << vec.size() << "* numbers now" << endl ;
cout << "output:" << endl ;
for ( it = vec.begin() ; it != vec.end() ; it ++ ){
cout << *it << " " ;
}
cout << endl << endl ;

//删除操作
cout << "erase:(begin , end)" << endl ;
int first , last ;
cin >> first >> last ;
if ( first < 0 || last > vec.size() ){
cout << "please enter again" << endl ;
cin >> first >> last ;
}
vec.erase(vec.begin() + first , vec.begin() + last) ;
if ( !vec.empty() ){
cout << "there are *" << vec.size() << "* numbers now" << endl ;
for ( it = vec.begin() ; it != vec.end() ; it ++ ){
cout << *it << " " ;
}
}else{
cout << "the vector is empty now!" << endl ;
}
cout << endl ;
return 0 ;
}

堆栈和队列容器

栈只能允许在链表或者数组的一段进行插入或者删除操作,此端被称为栈顶,另一端则被称为栈底。在栈顶进行的插入操作称为入栈(push),在栈顶进行的删除操作称为出栈(pop)。符合后进先出的原则(LIFO,Last In First Out)。

队列只允许在一端进行插入(push),此操作称为入队,此端称为队尾,而另一端进行删除(pop),此操作称为出队,此端称为队首。符合先进先出的原则(FIFO,First In First Out)。

包含头文件

#include –STL栈
#include –STL队列

创建

stack sta ;
queue que ;

插入或者删除元素

  • sta.push(elem) –往栈顶插入元素
  • sta.pop() –移除栈顶元素
  • que.push(elem) –往队尾插入元素
  • que.pop() –移除队首元素

访问元素

  • sta.top() –返回当前栈顶元素
  • que.front() –返回当前队首元素
  • que.back() –返回当前队尾元素
  • 对于栈和队列元素的访问,除上述方式外,唯一方式是遍历容器内容,并且移除访问过的每一个元素。

获取当前容器的容量大小

  • sta.size() –当前栈容器的容量大小
  • que.size() –当前队列容器的容量大小
  • sta.empty() –判断栈是否为空,若为空返回true
  • que.empty() –判断队列是否为空,若为空返回true

迭代器

  • 并无迭代器..

使用举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <iostream>
#include <stack>
#include <queue>

using namespace std ;

int main(){
cout << "enter the number of element:" << endl ;
int num ;
cin >> num ;
if ( num == 0 ){
cout << "please enter again" << endl ;
cin >> num ;
}

//创建存储数据类型为 int 的栈和队列容器
stack<int> sta ;
queue<int> que ;
cout << "enter elements of stack:" << endl ;
for ( int i = 0 ; i < num ; i ++ ){
cout << "input: " ;
int number ;
cin >> number ;
//往栈顶添加元素
sta.push(number) ;
}
cout << endl ;
cout << "enter elements of queue:" << endl ;
for ( int i = 0 ; i < num ; i ++ ){
cout << "input: " ;
int number ;
cin >> number ;
//往队尾添加元素
que.push(number) ;
}
cout << endl ;

cout << "the number of stack is " << sta.size() << endl ;
cout << "the number of queue is " << que.size() << endl ;
cout << endl ;

//访问栈顶元素
cout << "the top of stack is " << sta.top() << endl ;
//访问队首元素
cout << "the front of queue is " << que.front() << endl ;
//访问队尾元素
cout << "the back of queue is " << que.back() << endl ;
cout << endl ;

//访问栈元素
cout << "the elements of stack is " << endl ;
while ( !sta.empty() ){
cout << sta.top() << " " ;
sta.pop() ;
}
cout << endl ;
//访问队列元素
cout << "the elements of queue is " << endl ;
while ( !que.empty() ){
cout << que.front() << " " ;
que.pop() ;
}
return 0;
}

map容器

map容器中的元素通过比较键的关系使其有序。通过使用map容器可以建立一种由键到值的一一映照的对应关系,不允许有重复的键,但可以允许有重复的值,在某些题目中可以大大简化代码流程。

包含头文件

#include

创建

map map_ ;

插入或者删除元素

  • map_[key] = value –插入一个 key 到 value 关系的元素。
  • map_.insert(make_pair(key , value)) –效果同上。
  • map_erase(key) –移除键和参数匹配的元素。

迭代器

  • map::iterator it –创建一个map的正向迭代器

访问元素

  • map_[key] –返回key所对应的值
  • it->first –返回迭代器it所指向的map元素对应的键
  • it->second –返回迭代器it所指向的map元素对应的值
  • map_.begin() –返回一个指向第一个元素的迭代器指针
  • map_.end() –返回一个指向最后一个元素的后一个位置的指针

获取当前长度或者当前容量

  • map_.size() –获取当前元素个数
  • map_.empty() –若为空则返回true

使用举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <iostream>
#include <cstdio>
#include <set>
#include <cmath>
#include <vector>
#include <map>
#include <algorithm>

using namespace std ;

int main(){
string name ;
int grades ;
cout << "enter student`s name and grades(enter \"0 0\" to end):" << endl ;

//创建由string到int的映照关系 map_
map<string , int> map_ ;

while ( name[0] != '0' && grades != 0 ){
cin >> name >> grades ;
if ( name[0] != '0' && grades != 0 )
map_[name] = grades ;
}
cout << "there are " << map_.size() << " students now" << endl << endl ;
cout << "which student do you want to query?enter the name:" << endl ;

//创建map的正向迭代器it
map<string , int>::iterator it ;
while ( cin >> name ){
for ( it = map_.begin() ; it != map_.end() ; it ++ ){
if ( it->first == name ){
break ;
}
}
if ( it == map_.end() ){
cout << "please enter the name again!" << endl ;
}else{
break ;
}
}

//由键访问值
cout << "the " << name << "`s grades is " << map_[name] << endl ;
cout << "there is list:" << endl ;

for ( it = map_.begin() ; it != map_.end() ; it ++ ){
cout << it->first << " " << it->second << endl ;
}
cout << endl ;
cout << "which student do you want to remove?enter the name:" << endl ;

//移除和键匹配的此元素
while ( cin >> name ){
for ( it = map_.begin() ; it != map_.end() ; it ++ ){
if ( it->first == name ){
break ;
}
}
if ( it == map_.end() ){
cout << "please enter the name again!" << endl ;
}else{
break ;
}
}
map_.erase(name) ;

if ( !map_.empty() ){
cout << "there is list:" << endl ;
for ( it = map_.begin() ; it != map_.end() ; it ++ ){
cout << it->first << " " << it->second << endl ;
}
cout << endl ;
cout << "there are " << map_.size() << " students now" << endl ;
}else{
cout << "no students now!" << endl ;
}
return 0 ;
}

应用

POJ 2503 Babelfish
HrbustOJ 1987 逃课的孩子
HrbustOJ 1022 JiaoZhu and SC

写在最后

本篇文章进行过程中参考了大量资料,对wiki贡献者以及各博主对天性愚钝的我给予知识上的补充表示深深的感谢。