模板
函数模板
#include <iostream>
using namespace std;
//定义函数模板
//开始
template <class T> //class可以替换为typename
void mySwap(T &a,T &b){
T temp = a;
a = b;
b = temp;
}
//结束
int main(){
//使用函数模板
int a = 10;
int b = 20;
//自动类型推导
mySwap(a,b);
//显示指定类型(推荐)
mySwap<int>(a,b);
cout << "a = " << a << endl;
cout << "b = " << b << endl;
}
类模板
#include <iostream>
using namespace std;
template <class NameType,class AgeType>
class Person{
public:
NameType m_Name;
AgeType m_Age;
Person(NameType name,AgeType age){
this->m_Name = name;
this->m_Age = age;
}
void print_Message()
{
cout << m_Name << endl;
cout << m_Age << endl;
}
};
int main(){
Person<string,int> p1("张三",18);
p1.print_Message();
}
STL
STL六大组件:
- 容器
- 算法
- 迭代器
- 仿函数
- 适配器(配接器)
- 空间配置器
vector容器
//vector基本使用
#include <iostream>
using namespace std;
#include <vector>
int main(){
//创建vector容器
vector<int> v;
//向容器中插入数据
v.push_back(10);
v.push_back(20);
//第一种遍历方式
//v.begin()指向容器中第一个元素,v.end()指向容器中最后一个元素的下一个位置
for(auto it = v.begin();it < v.end();++it){
cout << *it << endl;
}
//第二种遍历方式
//i是v中的元素
for(int i : v){
cout << i << endl;
}
}
//vector存放自定义数据类型
#include <iostream>
using namespace std;
#include <vector>
class Person{
public:
Person(string name,int age){
this->m_Name = name;
this->m_Age = age;
}
string m_Name;
int m_Age;
};
int main(){
vector<Person> v;
Person p1("张三",18);
Person p2("李四",19);
v.push_back(p1);
v.push_back(p2);
for(auto it = v.begin();it < v.end();++it){
//注意:it是指针类型
cout << it->m_Name << ' ' << it->m_Age << endl;
}
}
//vector容器嵌套容器
#include <iostream>
using namespace std;
#include <vector>
int main(){
//大容器
vector<vector<int>> v;
//创建小容器
vector<int> v1;
vector<int> v2;
//给小容器赋值
for(int i = 0;i < 3;i++){
v1.push_back(i);
v2.push_back(i + 1);
}
//将小容器添加到大容器中
v.push_back(v1);
v.push_back(v2);
//遍历大容器
for(auto it = v.begin();it < v.end();++it){
//注意:*it是小容器
for(auto it1 = (*it).begin();it1 < (*it).end();++it1){
cout << *it1 << ' ';
}
cout << endl;
}
}
string容器
//string容器赋值操作
#include <iostream>
using namespace std;
#include <string>
int main(){
string str;
str.assign("hello C++"); //也可以直接str = "hello C++"
string str1;
str1.assign("hello C++",5);
string str2;
str2.assign(10,'w');
cout << str << endl << str1 << endl << str2;
//hello C++
//hello
//wwwwwwwwww
}
//string容器字符串拼接
#include <iostream>
using namespace std;
#include <string>
int main(){
//通过+号
string str = "hello";
str = str + " world";
//通过append
string str1 = "hello";
str1.append(" world");
cout << str << endl << str1 << endl;
}
//字符串查找和替换
#include <iostream>
using namespace std;
#include <string>
int main(){
//find从左往右查找
//rfind从右往左查找
string str = "hello";
//注意:find函数返回的是下标
int pos = str.find("ll");
if(pos == -1){
cout << "未找到字符串" << endl;
} else{
cout << "找到字符串,pos = " << pos << endl; // 找到字符串,pos = 2
}
string str1 = "hello";
str1.replace(1,3,"11111");
cout << str1 << endl; // h11111o
}
//string字符串比较
#include <iostream>
using namespace std;
#include <string>
int main(){
string str1 = "hello";
string str2 = "Hello";
//可以直接 == ,因为重载了
if(str1 == str2){
cout << "两个字符串相等" << endl;
} else{
cout << "两个字符串不相等" << endl;
}
}
//string字符存取
#include <iostream>
using namespace std;
#include <string>
int main(){
string str = "hello";
//遍历方式
//c是str中的元素
for(char c : str){
cout << c << ' ';
}
}
//string字符串插入和删除
#include <iostream>
using namespace std;
#include <string>
int main(){
string str = "hello";
str.insert(1,"111"); //在1号位置前插入
cout << str << endl; // h111ello
string str1 = "hello";
str1.erase(1,3); //从1号位置开始3个字符
cout << str1 << endl; // ho
}
//string子串
#include <iostream>
using namespace std;
#include <string>
void test(){
string email = "zhangsan@qq.com";
int pos = email.find('@');
string subStr = email.substr(0,pos);
cout << subStr << endl;
}
int main(){
string str = "hello";
//获得子串的方法:从下标1开始,截取3个字符(str不变)
string subStr = str.substr(1,3);
cout << subStr << endl; // ell
test(); // zhangsan
}
deque容器
//deque基本使用和vector类似
#include <iostream>
using namespace std;
#include <deque>
int main(){
deque<int> d;
//尾插
d.push_back(10);
//头插
d.push_front(20);
for(int i : d) {
cout << i << ' ' << endl; // 20 10
}
//赋值
deque<int> d1;
d1 = d;
for(int i : d1){
cout << i << ' ' << endl; // 20 10
}
}
//sort排序
#include <iostream>
using namespace std;
#include <deque>
#include <algorithm>
int main(){
deque<int> d;
d.push_back(30);
d.push_back(20);
d.push_front(10);
for(int i : d){
cout << i << ' ' << endl; // 10 30 20
}
sort(d.begin(),d.end());
for(int i : d){
cout << i << ' ' << endl; // 10 20 30
}
}
stack容器
//stack容器基本使用
#include <iostream>
using namespace std;
#include <stack>
int main(){
//栈(先进后出)不允许有遍历行为
stack<int> s;
//入栈
s.push(10);
s.push(20);
s.push(30);
while(!s.empty()){
cout << "栈顶元素:" << s.top() << endl;
//出栈
s.pop();
}
cout << s.size() << endl; // 0
}
queue容器
//queue容器基本使用
#include <iostream>
using namespace std;
#include <queue>
class Person{
public:
Person(string name,int age){
this->m_Name = name;
this->m_Age = age;
}
string m_Name;
int m_Age;
};
int main(){
//队列(先进先出)不允许有遍历行为
queue<Person> q;
Person p1("张三",18);
Person p2("李四",19);
q.push(p1);
q.push(p2);
while(!q.empty()){
//查看队头
cout << "队头元素:" << q.front().m_Name << ' ' << q.front().m_Age << endl;
//查看队尾
cout << "队尾元素:" << q.back().m_Name << ' ' << q.back().m_Age << endl;
//出队
q.pop();
}
cout << q.size() << endl; // 0
}
list容器
//list容器基本使用
#include <iostream>
using namespace std;
#include <list>
int main(){
list<int> l;
//尾插
l.push_back(10);
l.push_back(20);
//头插
l.push_front(30);
l.push_front(10);
//遍历
//不支持随机访问,即不可以用[]访问list容器中的元素
for(int i : l){
cout << i << endl;
}
//迭代器
auto it = l.begin();
//头删
l.pop_front();
//尾删
l.pop_back();
//移除该元素,有多少个移除多少个
l.remove(10);
}
//list容器反转和排序
#include <iostream>
using namespace std;
#include <list>
bool compare(int v1,int v2){
return v1 > v2;
}
int main(){
list<int> l;
l.push_back(10);
l.push_back(20);
l.push_back(30);
for(int i : l){
cout << i << ' '; // 10 20 30
}
cout << endl;
//反转
l.reverse();
for(int i : l){
cout << i << ' '; // 30 20 10
}
cout << endl;
//排序
//报错sort(l.begin(),l.end());
//所有不支持随机访问迭代器的容器,不可以用标准算法,但内部会提供对应一些算法
l.sort(); //默认升序
for(int i : l){
cout << i << ' '; // 10 20 30
}
cout << endl;
//降序
l.sort(compare); // 传入函数名
for(int i : l){
cout << i << ' '; // 30 20 10
}
}
'''排序案例:将Person自定义数据类型进行排序,Person中属性有姓名、年龄、身高。排序规则:按照年龄进行升序,如果年龄相同按照身高进行降序。
'''
#include <iostream>
#include <list>
using namespace std;
class Person{
public:
Person(string name,int age,int height){
this->m_Name = name;
this->m_Age = age;
this->m_Height = height;
}
string m_Name;
int m_Age{};
int m_Height{};
};
bool compare(const Person& p1,const Person &p2){
if(p1.m_Age == p2.m_Age){
return p1.m_Height > p2.m_Height; //身高降序
}else{
return p1.m_Age < p2.m_Age; //年龄升序
}
}
int main(){
Person p1("刘备",35,175);
Person p2("曹操",45,180);
Person p3("孙权",40,170);
Person p4("赵云",25,190);
Person p5("张飞",35,160);
Person p6("关羽",35,200);
list<Person> l;
l.push_back(p1);
l.push_back(p2);
l.push_back(p3);
l.push_back(p4);
l.push_back(p5);
l.push_back(p6);
l.sort(compare);
for(Person p : l){
cout << p.m_Name << ' ' << p.m_Age << ' ' << p.m_Height << endl;
}
//赵云 25 190
//关羽 35 200
//刘备 35 175
//张飞 35 160
//孙权 40 170
//曹操 45 180
}
set/multiset容器
set容器无重复元素
multiset容器允许有重复元素
//set容器基本使用
#include <iostream>
#include <set>
using namespace std;
int main(){
set<int> s;
//插入数据,只有insert方式
s.insert(10);
s.insert(30);
s.insert(20);
s.insert(30);
//set容器特点:所有元素插入后自动被排序、重复的元素会被过滤掉
for(int i : s){
cout << i << ' '; // 10 20 30
}
cout << endl;
//删除
s.erase(20);
for(int i : s){
cout << i << ' '; // 10 30
}
}
//set容器查找和统计
#include <iostream>
#include <set>
using namespace std;
int main(){
set<int> s;
//插入数据,只有insert方式
s.insert(10);
s.insert(30);
s.insert(20);
s.insert(30);
//find查找,返回迭代器指针(查到返回对应元素的迭代器,查不到返回m.end())
auto it = s.find(30);
if(it != s.end()){
cout << "找到了该元素: " << *it << endl; // 找到了该元素: 30
} else{
cout << "未找到该元素" << endl;
}
//count统计个数,值只能是1或者0
int num = s.count(30);
cout << num << endl; // 1
}
//pair对组基本使用
#include <iostream>
using namespace std;
int main(){
//有参构造
pair<string,int> p("Tom",15);
cout << p.first << ' ' << p.second << endl;
}
//set容器排序
#include <iostream>
using namespace std;
#include <set>
class compare{
public:
//仿函数
bool operator()(int a, int b){
return a > b;
}
};
int main(){
//排序,必须插入元素之前指定规则
set<int,compare> s1;
s1.insert(30);
s1.insert(20);
s1.insert(40);
s1.insert(25);
for(int i : s1){
cout << i << ' '; // 40 30 25 20
}
}
map/multimap容器
map容器:不允许容器中有重复的key值元素,按key值自动排序,每一个元素都是pair对组
multimap容器:允许容器中有重复key值元素
//map容器的基本使用
#include <iostream>
#include <map>
using namespace std;
int main(){
map<int,int> m;
m.insert(pair<int,int>(1,10));
m.insert(pair<int,int>(3,10));
m.insert((pair<int,int>(2,10)));
//遍历方式 或 for(auto it = m.begin();it != m.end();++it)
for(auto i : m){
//i是m中的元素
cout << i.first << ' ' << i.second << endl;
// 1 10
// 2 10
// 3 10
}
}
//map容器查找和统计
#include <iostream>
#include <map>
using namespace std;
int main() {
map<int, int> m;
m.insert(pair<int, int>(1, 10));
m.insert(pair<int, int>(3, 30));
m.insert((pair<int, int>(2, 20)));
//find通过key值查找,返回迭代器指针(查到返回对应元素的迭代器,查不到返回m.end())
auto it = m.find(3);
if(it != m.end()){
cout << "找到了该元素,value为:" << it->second << endl; // 30
} else{
cout << "没找到" << endl;
}
//count统计,值只能是1或0
int num = m.count(3);
cout << num << endl; // 1
}
//map容器排序
#include <iostream>
#include <map>
using namespace std;
class compare{
public:
//仿函数
bool operator()(const int &a, const int &b){
return a > b;
}
};
int main() {
//排序,必须先指定排序规则再插入
map<int, int,compare> m;
m.insert(make_pair(1, 10));
m.insert(make_pair(3, 30));
m.insert(make_pair(2, 20));
for(auto i : m){
cout << i.first << ' ' << i.second << endl;
}
}
函数对象
也叫仿函数,本质是类
谓词
#include <iostream>
using namespace std;
#include <vector>
//谓词:返回bool类型的仿函数
//一元谓词:operator()接受一个参数
//二元谓词:operator()接受两个参数
class GreaterFive{
public:
bool operator()(int val){
return val > 5;
}
};
int main(){
vector<int> v;
for(int i = 0;i < 10;i++){
v.push_back(i);
}
auto it = find_if(v.begin(),v.end(),GreaterFive());
if(it == v.end()){
cout << "没找到" << endl;
} else{
cout << "找到了:" << *it << endl; // 找到了:6
}
}
常用算法
//find和find_if用法
#include <iostream>
#include <vector>
using namespace std;
class GreaterFive{
public:
bool operator()(int a){
return a > 5;
}
};
int main(){
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
//find查找,返回迭代器
auto it = find(v.begin(),v.end(),10);
if(it == v.end()){
cout << "没找到" << endl;
} else{
cout << "找到了:" << *it << endl; // 找到了:10
}
//find_if查找
//注意:谓词传匿名对象,函数传函数名
auto it_if = find_if(v.begin(),v.end(),GreaterFive());
if(it_if == v.end()){
cout << "没找到" << endl;
} else{
cout << "找到了:" << *it_if << endl; // 找到了:10
}
}
//查找相邻重复元素
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(4);
v.push_back(4);
v.push_back(5);
auto it = adjacent_find(v.begin(),v.end());
if(it == v.end()){
cout << "找不到" << endl;
} else{
cout << "找到相邻重复元素" << *it << endl; // 找到相邻重复元素2
}
}
//二分查找(必须是有序序列),查找指定元素是否存在,返回bool值
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v;
v.push_back(1);
v.push_back(3);
v.push_back(2);
v.push_back(2);
v.push_back(4);
v.push_back(4);
v.push_back(4);
v.push_back(5);
sort(v.begin(),v.end());
bool b = binary_search(v.begin(),v.end(),2);
cout << b << endl; // 1
//count统计
int num = count(v.begin(),v.end(),4);
cout << num << endl; // 3
}
//求两个容器的交集、差集、并集
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> v1;
vector<int> v2;
for(int i = 0;i < 10;i++){
v1.push_back(i); // 0 1 2 3 4 5 6 7 8 9
v2.push_back(i + 5); // 5 6 7 8 9 10 11 12 13 14
}
//目标容器需要提前开辟空间
//求交集set_intersection
vector<int> v3;
v3.resize(min(v1.size(),v2.size()));
//返回迭代器
auto end = set_intersection(v1.begin(),v1.end(),v2.begin(),v2.end(),v3.begin());
for(auto it = v3.begin();it != end;++it){
cout << *it << ' '; // 5 6 7 8 9
}
cout << endl;
//求并集set_union
vector<int> v4;
v4.resize(v1.size() + v2.size());
auto end1 = set_union(v1.begin(),v1.end(),v2.begin(),v2.end(),v4.begin());
for(auto it = v4.begin();it != end1;++it){
cout << *it << ' '; // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
}
cout << endl;
//求差集set_difference
vector<int> v5;
v5.resize(max(v1.size(),v2.size()));
//v1 - v2
auto end2 = set_difference(v1.begin(),v1.end(),v2.begin(),v2.end(),v5.begin());
for(auto it = v5.begin();it != end2;++it){
cout << *it << ' '; // 0 1 2 3 4
}
}