目录
前言
STL即 Standard Template Library (标准模板库)的缩写,是C++自带的函数库,里面包含一些可以直接使用的类或者函数。例如 sort(排序)、string(字符串)、vector(变长数组)、list(双向链表)、map(key-value对应关系)、set(集合)、queue(队列)、priority_queue(优先级队列)、stack(栈)等。
1. 模板
1.1 函数模板
所谓函数模板,实际上是建立一个通用函数,它所用到的数据的类型(包括返回值类型、形参类型、局部变量类型)可以不具体指定,而是用一个虚拟的类型来代替(实际上是用一个标识符来占位),等发生函数调用时再根据传入的实参来逆推出真正的类型。这个通用函数就称为函数模板(Function Template)。
template<typename T> //此时可以把T当做一种类型
void Swap(T &a, T &b)//当时用该函数的时候,编译器会根据参数类型自动判断T是什么类型
{
T temp = a;
a = b;
b = temp;
}//建议直接使用自带的函数swap()
int main(){
//交换 int 变量的值
int n1 = 100, n2 = 200;
Swap(n1, n2);
cout<<n1<<", "<<n2<<endl;
//交换 float 变量的值
float f1 = 12.5, f2 = 56.93;
Swap(f1, f2);
cout<<f1<<", "<<f2<<endl;
//交换 char 变量的值
char c1 = 'A', c2 = 'B';
Swap(c1, c2);
cout<<c1<<", "<<c2<<endl;
//交换 bool 变量的值
bool b1 = false, b2 = true;
Swap(b1, b2);
cout<<b1<<", "<<b2<<endl;
return 0;
}
1.2 类模板
函数模板中定义的类型参数可以用在函数声明和函数定义中,类模板中定义的类型参数可以用在类声明和类实现中。类模板的目的同样是将数据的类型参数化。一但声明了类模板,就可以将类型参数用于类的成员函数和成员变量了。换句话说,原来使用 int、float、char 等内置类型的地方,都可以用类型参数来代替。
注意:
1. 使用类模板创建对象时,需要指明具体的数据类型。请看代码:Point<int, int> p1(10, 20);
2. 与函数模板不同的是,类模板在实例化时必须显式地指明数据类型,编译器不能根据给定的数据推演出数据类型。Point<int, int> p1(10, 20);
3. 赋值号两边都要指明具体的数据类型,且要保持一致。 Point<char*, char*> *p3 = new Point<char*, char*>("东经180度", "北纬210度");
假如我们现在要定义一个类来表示坐标,要求坐标的数据类型可以是整数、小数和字符串,例如:
- x = 10、y = 10
- x = 12.88、y = 129.65
- x = "东经180度"、y = "北纬210度"
#include <iostream>
using namespace std;
template<class T1, class T2> //这里不能有分号
class Point{
public:
Point(T1 x, T2 y): m_x(x), m_y(y){ }
public:
T1 getX() const; //获取x坐标
void setX(T1 x); //设置x坐标
T2 getY() const; //获取y坐标
void setY(T2 y); //设置y坐标
private:
T1 m_x; //x坐标
T2 m_y; //y坐标
};
template<class T1, class T2> //模板头
T1 Point<T1, T2>::getX() const /*函数头*/ {
return m_x;
}
template<class T1, class T2>
void Point<T1, T2>::setX(T1 x){
m_x = x;
}
template<class T1, class T2>
T2 Point<T1, T2>::getY() const{
return m_y;
}
template<class T1, class T2>
void Point<T1, T2>::setY(T2 y){
m_y = y;
}
int main(){
Point<int, int> p1(10, 20);
cout<<"x="<<p1.getX()<<", y="<<p1.getY()<<endl;
Point<int, char*> p2(10, "东经180度");
cout<<"x="<<p2.getX()<<", y="<<p2.getY()<<endl;
Point<char*, char*> *p3 = new Point<char*, char*>("东经180度", "北纬210度");
cout<<"x="<<p3->getX()<<", y="<<p3->getY()<<endl;
return 0;
}
2. 常用容器
2.1 string容器(字符串)
2.1.1 基本操作
//1.使用
string str; //默认为“”空字符串
string str1="hello"; //初始化为“hello”
//2.输入
cin>>str; //读入一个串(空格为中间符)abc cd 只读入abc
getline(cin,str); //读入一行。abc cd 全部读入
//3.输出
cout<<str; //输出整个string
cout<<str[0]; //输出string第一个字符
2.1.2 基本语法
赋值运算符:= o(n)
比较运算符:== != < <= > >=按字典序比较o(n) 连接运算符:+ +=将第二个串拼接到第一个后面o(n)
s[index]返回字符串s中下标为index的字符(下标从0开始)o(1) s.substr(p,n)返回从s的下标p开始的n个字符组成的字符串o(n) s.length返回字符串的长度O(1)
s.empty()判断s是否为空o(1)
s.erase(p0,len)删除s中从p0开始的len个字符,如果len省略则删除p0及后面全部字符o(n)
s.erase(s.begin( )+i)删除前i个字符o(n)
s1.find(s2,pos)从前往后,查找成功时返回第一次出现的下标,失败返回 string : :npos的值(-1) o(n*m)
2.2 vector容器(变长数组)
2.2.1 基本操作
vector是能够存储多个相同类型元素的容器(类似于数组)
//声明:
template<
class T,
class Allocator = std::allocator<T>
>class Vector;
//使用
vector<int> vec;//一个存储int类型的vector,默认size是0
vector<int> vec(n);//一个存储int类型变量的vector,size为n
//输入:
//1.size为0:
cin>>tem;//读入
vec.push_back(tmp);//将tmp推入vec的末尾
//2.size为n
cin>>vec[i];//写入vec的第i个元素(下标从0开始)
//输出
for(int i=0;i<vec.size();i++) cout<<vec[i];//vec.size()为vec内元素个数
for(auto it:vec) cout<<it;//range-based loop
2.2.2 基本语法
v[i] 返回v中第i个元素(下标从0开始) o(1)
v.push_back(var) 向v后面添加一个元素var o(1) v.pop_back() 删除v最后一个元素o(1)
v.size() 获取v中元素个数,返回size_t类型变量o(1) v.resize(int n) 把v的容量改为n个元素o(n)
v.empty() 判断v是否为空o(1)
v.clear() 清空v o(size)
v.insert(it,x) 向迭代器it指向元素前增加一个元素x o(n) v.erase(it) 删除向量中迭代器指向元素o(n)
v.front() 返回首元素的引用o(1)
v.back() 返回尾元素的引用o(1)
v.begin() 返回指向第一个元素的迭代器o(1)
v.end() 返回指向最后一个元素的下一个位置迭代器o(1)
2.3 list容器(双向链表)
2.3.1 基本操作
list是由双向链表实现的存储容器。
//声明:
template<
class T,
class Ailocator = std: :allocator<T>
>class list;
//使用:
list<int> lis; //一个存储int类型变量的list,默认size为空
//插入:
//前端插入:
lis.push_front(item); //从list前端插入
//后端插入:
lis.push_back(item); //从list后端插入
//中间插入:
auto it=find(iis.begin(),lis.end(),val);
if(it!=lis.end()) lis.insert(it,item); //找到list中第一个值为val的元素,插入到其前方
//输出:
for(auto it=lis.begin();it!=lis.end();it++) cout<<*it;
for(auto it:lis) cout<<it; //range-based loop
2.3.2 基本语法
lis.push_front(var) 向lis前面添加一个元素var o(1) lis.push_back(var) 向lis后面添加一个元素var o(i) lis.pop_front() 删除lis第一个元素o(1)
lis.pop_back() 删除lis最后一个元素o(1)
lis.size()获取lis中元素个数,返回size_t类型变量o(1) lis.resize(int n) 把lis的容量改为n个元素o(n)
lis.empty() 判断v是否为空o(1)
lis.clear() 清空lis o(size)
lis.insert(it,×) 向迭代器it指向元素前增加一个元素x o(1) lis.erase(it) 删除向量中迭代器指向元素o(1)
lis.front() 返回首元素的引用o(1)
lis.back() 返回尾元素的引用o(i)
lis.begin() 返回指向第一个元素的迭代器o(1)
lis.end()返回指向最后一个元素的下一个位置迭代器o(1)
2.4 queue容器(队列)
队列是一种先进先出的数据结构
2.4.1 基本操作
//声明:
template<
class T,
class Container = std::deque<T>
> class queue;
//使用:
queue<int> q; //建立一个存储int类型的队列q使用方法:
q.push(item) //在q的最后添加一个type类型元素item o(1)
q.pop() //使q最前面的元素出队o(1)
q.front() //获取q最前面的元素o(1)
q.size() //获取q中元素个数o(1)
q.empty() //判断q是否为空o(1)
2.4.2 priority_queue(优先级队列)
优先级队列按照元素的优先级顺序,从高到低弹出元素
//声明:
template<
class T,
class Container = std:: vector<T> ,
class compare =std::less<typename container ::value_type>
class priority_queue;
//使用:
priority_queue<int> pq; //建立一个存储int类型的优先级队列pq使用方法:
pq.push(item) //在pq中添加一个元素item o(1ogn)
pq.pop() //使pq最前面的元素出队o(1)
pq.front() //获取pq最前面的元素o(logn)
pq.size() //获取pq中元素个数O(1)
pq.empty() //判断pq是否为空o(1)
2.5 stack(栈)
栈是一种先进后出的数据结构
//声明:
template<
class T,
class Container = std::deque<T>
> class stack;
//使用:
stack<int> s;建立一个存储int类型的栈s
使用方法:
s.push(item) //在s的顶层压入一个type类型元素item o(1)
s.pop() //使s最上层的元素出栈o(1)
s.top() //获取s最上层的元素o(1)
s.size() //获取s中元素个数o(1)
s.empty() //判断s是否为空o(1)
3. 常用算法
3.1 sort(排序)
声明:
template <class RandomIt,class Compare>
void sort(RandomIt first,RandomIt last,Compare comp);
使用:
int a[ ]={3,5,6,7,8,4,2,1,9}
sort(a,a+9); //默认是从小到大
//1,2,3,4,5,6,7,8,9
int a[ ]={3,5,6,7,8,4,2,1,9}
sort(a,a+9,1ess<int>()); //从小到大
//1,2,3,4,5,6,7,8,9
int a[]={3,5,6,7,8,4,2,1,9}
sort(a,a+9,greater<int>()); //从大到小
//9,8,7,6,5,4,3,2,1
bool cmp(int a,int b){
return a<b;
}
int a[ ]={3,5,6.7,8,4,2,1,9};
sort(a, a+9, cmp); //从小到大1,2,3,4,5,6,7,8,9
bool cmp(int a,int b){
return a>b;
}
int a[ ]={3,5,6,7,8,4,2,1,9}
sort(a, a+9,cmp); //从大到小
//9,8,7,6,5,4,3,2,1