C++ 标准模板库的核心包括以下三个组件:
组件 描述
容器(Containers) 容器是用来管理某一类对象的集合。C++ 提供了各种不同类型的容器,比如 deque、list、vector、map 等。
算法(Algorithms) 算法作用于容器。它们提供了执行各种操作的方式,包括对容器内容执行初始化、排序、搜索和转换等操作。
迭代器(iterators) 迭代器用于遍历对象集合的元素。这些集合可能是容器,也可能是容器的子集。
这三个组件都带有丰富的预定义函数,帮助我们通过简单的方式处理复杂的任务。
本文简要介绍:
- vector
- set
- list
- queue
- map
不定长数组:vector
vector是一个模板类,所以需要用vector<int>a或者vector<double>b来声明一个vector。vector<int>是一个类似于int a[]的整数数组,而vector<string>就是一个类似于string a[]的字符串数组。
**相比于数组的优势:**可以直接赋值,还可以作为函数的参数或者返回值,而无需像传递数组那样另外用一个变量指定元素个数。
vector的使用:
要想用vector首先得包含头文件vector
#include <vector>
常用操作:
#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
template <typename T> //定义一个模板
void showvector(vector<T> v)// 使用迭代器 iterator 访问值
{
for (vector<T>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it;
}
cout << endl;
}
int main(int argc, char const *argv[])
{
vector<int>a;//初始化vector
for(int i = 0; i < 5; i++){ //插入5个顺序元素
a.push_back(i);//向尾部插入
}
cout<<a.size()<<endl;//输出vector长度
for(int i = 0; i < a.size(); i++){// 访问向量中的 5 个值
cout << "value of vec [" << i << "] = " << a[i] << endl;
}
cout<<a.size()<<endl;//输出vector的长度
a.resize(4);//修改长度
cout<<a[4] <<endl;//虽然长度变了,但是之前存入的值还是能被访问到
a.pop_back(); //删除最后一个元素
a.insert(a.begin()+1,9); //在第二个位置插入新元素
a.insert(a.begin() + 1, 8,8); //连续插入8个8
a.erase(a.begin() + 3); //删除第四个元素
a.erase(a.begin(),a.begin()+3); //连续删除3个元素
for(int i = 0; i < a.size(); i++){// 访问向量中的 5 个值
cout << "value of vec [" << i << "] = " << a[i] << endl;
}
a.clear(); //清除所有内容
}
集合set
set就是数学上的集合—每个元素最多只出现一次。set里面的元素是有序的且唯一的,只要你往set里添加元素,它就会自动排序,而且,如果你添加的元素set里面本来就存在,那么这次添加操作就不执行。和sort一样,自定义类型也可以构造set,但同样必须定义“小于”运算符
-
不能直接改变元素值,因为那样会打乱原本正确的顺序,要改变元素值必须先删除旧元素,则插入新元素
-
不提供直接存取元素的任何操作函数,只能通过迭代器进行间接存取,而且从迭代器角度来看,元素值是常数
-
元素比较动作只能用于型别相同的容器(即元素和排序准则必须相同)
#include <iostream>
#include <set>
#include <string>
#include <vector>
using namespace std;
void showset(set<string> &v)
{
for (set<string>::iterator it = v.begin(); it != v.end(); it++)
cout << *it<<endl;
}
int main()
{
set<string> s;
s.insert("sfsf");//往set里面添加元素
s.insert("abb");
s.insert("cds");
s.erase(s.begin());//删除,注意不同于vector,只能一个个删除
s.erase("sfsf");//或者删除指定元素
showset(s);
return 0;
}
链表list
list是一个双向链表,而单链表对应的容器则是foward_list。
list即双向链表的优点是插入和删除元素都比较快捷,缺点是不能随机访问元素
值得注意的是,list容器不能调用algorithm下的sort函数进行排序,因为sort函数要求容器必须可以随机存储,而list做不到。所以,list自己做了一个自己用的排序函数。
list<int> l1{ 8,5,7,6,1,2,3,4,5,5,6,7,7 };
l1.sort();
queue
queue 模板类的定义在头文件中。
与stack 模板类很相似,queue 模板类也需要两个模板参数,一个是元素类型,一个容器类
型,元素类型是必要的,容器类型是可选的,默认为deque 类型。
定义queue 对象的示例代码如下:
queue q1;
queue q2;
queue 的基本操作有:
入队,如例:q.push(x); 将x 接到队列的末端。
出队,如例:q.pop(); 弹出队列的第一个元素,注意,并不会返回被弹出元素的值。
访问队首元素,如例:q.front(),即最早被压入队列的元素。
访问队尾元素,如例:q.back(),即最后被压入队列的元素。
判断队列空,如例:q.empty(),当队列空时,返回true。
访问队列中的元素个数,如例:q.size()
#include <cstdlib>
#include <iostream>
#include <queue>
using namespace std;
int main()
{
int e,n,m;
queue<int> q1;
for(int i=0;i<10;i++)
q1.push(i); //向队尾插入元素
if(!q1.empty()) cout<<"queue is not empty";//判断是否为空
n=q1.size();//返回队列内元素的数目
cout<<n<<endl;
m=q1.back();//访问队尾元素
cout<<m<<endl;
for(int j=0;j<n;j++)
{
e=q1.front();//访问队首元素
cout<<e<<" ";
q1.pop();//弹出队首元素
}
return 0;
}
map
map运用了哈希表地址映射的思想,也就是key-value的思想,来实现的。
声明
例:
map<string,int>;//声明一个key为string,value为int的map
常用函数
clear
清除 map 中所有元素;
erase
删除 map 中指定位置的元素;
insert
在 map 指定位置添加 pair 类型的元素;
find
获取 map 中元素的迭代器;
begin, end
map 的正向迭代器的起始位置与终点位置;
rbegin, rend
// 1. 直接定义
map<char,int> mymap;
mymap['a'] = 10;
// 2. 复制
map<char, int> second(mymap);
//修改值
second['a']=1002;
//使用insert函数插入
mymap.insert(pair<char,int>('f',100) );
本文主要参考:
- 《算法竞赛入门经典(第二版)》
- C++ STL快速入门