【C++】标准模板库(上)

C++ STL(标准模板库)是一套功能强大的 C++ 模板类,提供了通用的模板类和函数,这些模板类和函数可以实现多种流行和常用的算法和数据结构,如向量、链表、队列、栈。
vector封装数组,list封装了链表,map和set封装了二叉树等
一、vector
vector是一种「变长数组」,即“自动改变数组长度的数组”。
vector可以用来以邻接表的方式储存图,非常友好,非常简洁。
2.定义
可以像定义变量一样来定义一个vector类型的数组。
vector<int> a;
其中尖括号中的类型可以换成其他的任何类型,也可以换成一个vector<int>的类型,这时,就相当于定义了一个二维的数组,其元素的个数是可变的,并且其元素的元素的个数也是可变的。
vector<vector<int> > b;
注意:vector<vector
还有另外一种二维数组的定义方法
vector<int> c[100];
这种定义在算法中经常会用到,因为题目上大概率会把第一维的最大值给定。
3.元素访问
vector一般有两种访问方式,第一种最直接也最常用:
1.通过下标访问
这个和数组相似,可以直接使用a[i][j]进行访问。
2.通过迭代器访问
迭代器(iterator)可以理解为指针:
在使用之前要先定义一个迭代器:
vector<类型名>::iterator 变量名;
举个例子:
#include <iostream>
#include <vector>
using namespace std;
int main(){
vector<int> v;
for (int i = 0; i < 5; i++)
{
v.push_back(i);
}
//v.begin()返回v的首元素地址
vector<int>::iterator it=v.begin();
for (int i = 0; i < v.size(); i++)
{
cout<<it[i]<<" ";
}
return 0;
}
其中定义迭代器类型的代码vector<int>::iterator it=v.begin();可以简写为auto it = v.begin();因为这里的v.begin()类型就是一个迭代器类型,赋值后,auto会根据赋值号右边的类型赋给左边。
for (vector<int>::iterator it=v.begin(); it!=v.end();it++){
cout<<*it<<" ";
}
也可以使用这种方式进行遍历。
3.常用函数
(1)push_back()
push_back(item)就是在vector后面添加一个元素item
(2)pop_back()
push和pop时一对反义词,学过数据结构的人都知道,栈元素的压入和弹出就是push和pop。
须知,pop_back()一次弹出一个元素,vector容器就会减少一个预算。
(3)size()
szie()返回vector中所含元素的个数,时间复杂度为O(1)
(4)clear()
clear()用于一键清空vector中的所有元素,时间复杂度为O(N),其中N为vector中原属和元素的个数。
(5)insert()
insert(要插入的地址,要插入的元素);
与push_back()无脑在尾部添加元素不同的是,insert()是根据指定位置在vector中插入元素。
v.insert(v.begin()+2,-1); //将-1插入v[2]的位置
(6)erase()
同样,与clear()简单粗暴清空vector不同的是erase(),删除指定位置的元素。
erase()有两种用法:
删除一个元素(erase(index); )
//删除v[3]
v.erase(v.begin()+3);
删除一个区间内的元素
//删除v[1]到v[4]的元素
v.erase(v.begin()+1,v.begin()+4);
4.vector常见用途
(1)储存数据
vector本身可以作为数组使用,而且在一些元素个数不确定的场合可以很好地节省空间。
(2)用邻接表存储图
使用vector实现邻接表,更为简单。
二、set
1.set的定义
像定义变量一样定义set变量:
set<类型名> 变量名;
类型名可以是int、double、char、struct,也可以是STL容器:vector、set、queue。
用例:
set<int> name;
set<double> name;
set<char> name;
set<struct node> name;
set<set<int> > name;//注意:> >之间要加空格
set数组的定义和vector相同:
set<类型名> array[SIZE];
例如:
set<int> arr[10];
2.set容器内元素的访问
set只能通过迭代器(iterator)访问:
set<int>::iterator it;
set<char>::iterator it;
这样,就得到了迭代器it,并且可以通过*it来访问set里的元素。
注意:
除了vector和string之外的STL容器都不支持*(it+i)的访问方式,因此只能按照如下方式枚举:
int main()
{
set<int> st;
st.insert(5);
st.insert(2);
st.insert(6);
for (set<int>::iterator it = st.begin(); it != st.end(); it++)
{
cout << *it << endl;
}
return 0;
}
set内部的元素会自动递增排序,并且晒去了重复元素。
3.常用函数
- 插入元素 (
insert())
使用insert()函数可以向set中插入一个元素。
set<char> st;
st.insert('A');
- 查找元素 (
find())
当查找一个不存在的元素时(比如数字2),find()会返回end()迭代器,你不能直接解引用它,否则会引发错误。你应该先检查find()的返回值是否等于end()。
set<char>::iterator it = st.find('A');
if (it != st.end()) {
cout << *it << endl;
} else {
cout << "Element not found" << endl;
}
或者使用*(st.find('A'))的方式,但同样需要先检查返回值。
- 删除元素 (
erase())
如果删除一个不存在的元素(如st.find(100)),find()将返回end(),你不能直接传递给erase()。
// 删除单个元素
set<char>::iterator it = st.find('A');
if (it != st.end()) {
st.erase(it);
}
// 删除区间元素
it = st.find('some_value');
if (it != st.end()) {
st.erase(it, st.end());
}
注意,删除区间元素时,你需要确保find()返回的迭代器不是end(),否则你不能从end()迭代器开始删除。
- 获取元素个数 (
size())
size()函数返回set中的元素个数,时间复杂度为O(1)。
cout << st.size() << endl;
- 返回元素 (
begin()和end())
begin()返回指向set中第一个元素的迭代器,而end()返回指向set“尾部之后”的迭代器。你不能解引用end()返回的迭代器,它通常用作一个哨兵值,表示序列的结束。
if (!st.empty()) {
cout << *st.begin() << endl; // 输出第一个元素
}
- 判断容器是否为空 (
empty())
这部分是正确的。empty()函数返回一个布尔值,表示set是否为空。
if (st.empty()) {
cout << "The set is empty" << endl;
} else {
cout << "The set is not empty" << endl;
}
4.自定义比较函数
-
元素不是结构体
struct myComp { bool operator()(const int &a,const int &b) { return a-b>0; } }; set<int,myComp>s; int main() { s.insert(1); cout<<s.size(); } -
元素是结构体类型
struct Info {
string name;
float score;
//重载“<”操作符,自定义排序规则
bool operator < (const Info &a) const {
//按score从大到小排列
return a.score<score;
}
};
set<Info> s;
int main() {
Info t;
t.name="zhangsan";
t.score=1.0;
s.insert(t);
set<Info>::iterator a=s.begin();
cout<<(*a).name<<" "<<(*a).score;
}
三、map
map是STL(中文标准模板库)的一个关联容器。
- 可以将任何基本类型映射到任何基本类型。如char array[100]事实上就是定义了一个int型到char型的映射。
- map提供一对一的数据处理,key-value键值对,其类型可以自己定义,第一个称为关键字,第二个为关键字的值
- map内部是自动排序的
1.定义
map<type1name,type2name> maps;//第一个是键的类型,第二个是值的类型
map<string,int> maps;
2.访问
-
通过下标访问:
- 如:maps["as"]=5;
-
迭代器访问:
-
int main() { map<char,int> maps; maps['A']=1; maps['B']=2; maps['C']=3; for(map<char,int>::iterator it = maps.begin();it!=maps.end();it++) { cout<<it->first<<" "<<it->second<<endl; //使用it->first来访问键,使用it->second访问值 } }
-
3.常用函数
-
maps.insert() 插入
-
maps.insert(pair<char,int>('D',4)); maps.insert(map<char,int>::value_type('E',5));
-
-
maps.find()查找
-
cout<<(maps.find('A'))->first;
-
-
maps.clear()清空
-
maps.erase()删除元素
-
maps.erase(maps.find('A'));//迭代器删除 int t = maps.erase('B');//成功删除返回1
-
-
maps.empty()判断其是否为空
-
maps.swap()交换两个map
-
maps.swap(map1);
-
-
maps.begin()返回指向map头部的迭代器
-
maps.end()返回指向map末尾的迭代器
-
maps.size()长度

浙公网安备 33010602011771号