C++进阶编程

范型编程,模板

目的:建立通用的模具,提高复用性

  • 模板不可以直接使用,它只是一个框架
  • 模板的通用性并不是万能的

函数模板

template
template声明创建模板
typename可以用class代替
T通用的数据类型

template<typename T>//或者template<class T>,T需要在以下指定具体的数据类型
void swap(T&a,T&b){//a和b的数据类型一致
	T temp=a;
	a=b;
	b=temp;
}
void test(){
	int a=10;
	int b=20;
	char c='1';
	swap(a,b);//自动类型推导
	swap(a,c);//错误,要求数据类型一致
	//或者 swap<int>(a,b);//显示指定类型
	cout<<"a="<<a<<" b="<<b<<endl;
}

普通函数和函数模板的区别

普通函数调用可以发生隐式类型转换
普通模板用自动类型推导,不可以发生隐式类型转换
函数模板用显示指定类型,可以发生隐式类型转换

int myadd(int a,int b){
	return a+b;
}
template<typename T>
T myadd2(T a,T b){
	return a+b;
}
void test(){
	int a=10;
	char b='a';
	cout<<"a+b="<<myadd(a,b)<<endl;//发生隐式类型转换,b的类型变为整型=65
	myadd2(a,b);//报错
	myadd2<int>(a,b);//不报错,b的类型自动转为int类型
}

普通函数和函数模板的调用规则

如果普通函数和函数模板都可以调用,优先调用普通函数
可以通过空模板参数列表强制调用函数模板
函数模板可以发生函数重载
如果函数模板可以产生更好的匹配,优先调用函数模板

void myPrint(int a,int b){
	cout<<"调用普通函数"<<endl;
}
template<class T>
void myPrint(T a, T b){
	cout<<"调用函数模板"<<endl;
}
void myPrint(T a, T b, T c){//重载
	cout<<"调用函数模板"<<endl;
}
void test(){
	int a=10;
	int b=10;
	int c=10;
	char d='d';
	char e='e';
	myprint(a,b);//调用普通函数
	myprint<>(a,b);//空模板强制调用函数模板
	myprint(a,b,c);//调用函数模板
	myprint(d,e);//调用函数模板
}

模板的局限性

有些特定的数据类型需要用具体化方式做特殊实现

template<typename T>
bool mycompare(T&a,T&b){
	if(a==b){
		return true;
	}
	return false;
}
class Person{
public:
	string Name;
	int Age;
	Person(string name,int age){
		Name=name;
		Age=age;
	}
}
template<> bool mycompare(Person&a,Person&b){//重写Person类的函数实现
	if(a.Name==b.Name && a.Age==b.Age){
		return true;
	}
	return false;
}
void test(){
	int a=10;
	int b=10;
	bool res=mycompare(a,b);
	if(res){cout<<"a==b"<<endl;}
	else{cout<<"a!=b"<<endl;}
}
void test2(){
	Person p1("Tom",12);
	Person p2("Tom",12);
	bool res2=mycompare(p1,p2);//没有写template<> bool mycompare函数之前报错,无法对比特定数据类型,写了之后正确
}

类模板

template下面写类

template<class NameType,class AgeType>
class Person{
public:
	NameType Name;
	AgeType Age;
	Person(NameType name,AgeType age){
		Name=name;
		Age=age;
	}
	void showPerson(){
		cout<<"名字:"<<Name<<" 年龄:"<<Age<<endl;
	}
}
void test(){
	Person<string,int> p1("孙",999);
	p1.showPerson();
}

类模板和函数模板的区别

  • 类模板没有自动类型推导
  • 类模板在模板参数列表中可以有默认参数
template<class NameType,class AgeType=int>//AgeType类型默认int
class Person{
public:
	NameType Name;
	AgeType Age;
	Person(NameType name,AgeType age){
		Name=name;
		Age=age;
	}
	void showPerson(){
		cout<<"名字:"<<Name<<" 年龄:"<<Age<<endl;
	}
}
void test(){
	Person p1("孙",999);//报错
	Person<string,int> p1("孙",999);//只能用显式指定类型
	p1.showPerson();
	Person<string> p2("孙",999);//正确
}

类模板中成员函数创建时机

类模板中成员函数在调用时才去创建

class Person1{
public:
	void showPerson1{
		cout<<"show person1"<<endl;
	}
}
class Person2{
public:
	void showPerson2{
		cout<<"show person2"<<endl;
	}
}
template<class T>
class MyClass{
public:
	T obj;
	//类模板中的成员函数在调用时才去创建,不是一开始就调用
	void func1(){
		obj.showPerson1();
	}
	void func2(){
		obj.showPerson2();
	}
}
void test(){
	MyClass<Person1>m;
	m.func1();//正确
	m.func2();//报错
}

类模板对象做函数参数

类模板对象做函数参数

#include<string>
template<class NameType,class AgeType=int>//AgeType类型默认int
class Person{
public:
	NameType Name;
	AgeType Age;
	Person(NameType name,AgeType age){
		Name=name;
		Age=age;
	}
	void showPerson(){
		cout<<"名字:"<<Name<<" 年龄:"<<Age<<endl;
	}
}
void printPerson(Person<string,int> &p){//指定传入类型,最常用!
	p.showPerson();
}
template<class T1,class T2>
void printPerson2(Person<T1,T2> &p){//参数模板化
	p.showPerson();
	cout<<"T1的类型:"<<typeid(T1).name()<<endl;//输出数据类型
}
template<class T>
void printPerson3(T &p){//整个类模板化
	p.showPerson();
	cout<<"T的类型:"<<typeid(T).name()<<endl;//输出类的数据类型
}
void test(){
	Person<string,int>p('孙',999);
	printPerson(p);//正确
	printPerson2(p);//正确
	printPerson3(p);//正确
}

类模板与继承

  • 当子类继承的父类是一个类模板时,子类在声明时,要指定父类中T的类型
  • 如果不指定,编译器无法给子类分配内存
  • 如果想灵活指定出父类中T的类型,子类也需变为类模板
template<class T>
class Base{
	T m;
}
class Son:public Base{}//错误
class Son:public Base<int>{}//必须指定一个类型
template<class T1,class T2>
class Son2:public Base<T2>{
public:
	T1 obj;
	Son2(){
		cout<<"T1的数据类型:"<<typeid(T1).name()<<" T2的数据类型:"<<typeid(T2).name()<<endl;
	}
}
void test(){
	Son2<int,char> s;//T1:int,T2:char
}

类模板成员函数类外实现

#include<string>
template<class NameType,class AgeType=int>//AgeType类型默认int
class Person{
public:
	NameType Name;
	AgeType Age;
	Person(NameType name,AgeType age);
	void showPerson();
}
template<class NameType,class AgeType=int>
Person<NameType,AgeType>::Person(NameType name, AgeType age){//需要加上类模板的参数列表
	this->Name=name;
	this->Age=age;
}
template<class NameType,class AgeType=int>
void Person<NameType,AgeType>::showPerson(){
		cout<<"名字:"<<this->Name<<" 年龄:"<<this->Age<<endl;
	}

类模板分文件编写

类模板中的成员函数一开始并不创建
分文件编写时包含的是.h声明文件,由于创建时机是在调用阶段,导致分文件编写时链接不到。
第一种解决方法:在主文件中直接包含源文件.cpp
第二种解决(主流)方法:将.h声明文件和.cpp实现文件的内容都放到一起,命名为.hpp

类模板与友元

全局函数类内实现:直接在类内声明友元即可,比较简单推荐
全局函数类外实现:需要提前让编译器知道全局函数的存在,过于复杂

template<class T1,class T2>
class Person;//全局函数类外实现,提前让编译器知道Person类的存在
template<class T1,class T2>//全局函数类外实现,提前让编译器知道
void printPerson2(Person<T1,T2>& p){
	cout<<"类外实现,名字:"<<p.Name<<" 年龄:"<<p.Age<<endl;
}

template<class T1,class T2>
class Person{
public:
	//全局函数类内实现
	friend void printPerson(Person<T1,T2>& p){
		cout<<"类内实现,名字:"<<p.Name<<" 年龄:"<<p.Age<<endl;
	} 
	friend void printPerson2<>(Person<T1,T2>& p);//全局函数类外实现,需要添加空模板参数列表
	Person(T1 name,T2 age){
		this->Name=name;
		this->Age=age;
	}
private:
	T1 Name;
	T2 Age;
}

void test(){
	Person<string,int>p("Tom",22);
	printPerson(p);
	printPerson2(p);
}

STL(标准模板库)常用容器

vector存放标准数据类型

#include<vector>
#include<algorithm>
void myPrint(int val){
	cout<<val<<endl;
}
void test(){
	vector<int> v;
	v.push_back(10);
	v.push_back(20);
	v.push_back(30);
	v.push_back(40);
	//第一种遍历方法
	vector<int>::iterator itBegin=v.begin();
	vector<int>::iterator itEnd=v.end();
	while(itBegin!=itEnd){
		cout<<*itBegin<<endl;
		itBegin++;
	}
	//第二种遍历方法
	for(vector<int>::iterator it=v.begin();it!=v.end();it++){
		cout<<*it<<endl;
	}
	//第三种遍历方法
	for_each(v.begin(),v.end(),myPrint);//myPrint(*v.begin())
}

vector存放自定义数据类型

存放自定义数据类型

#include<vector>
#include<algorithm>
#include<string>
class Person{
public:
	string Name;
	int Age;
	Person(string name,int age){
		Name=name;
		Age=age;
	}
}
void myPrintPerson(Person p){
	cout<<"姓名:"<<p.Name<<" 年龄:"<<p.Age<<endl;
}
void test(){
	vector<Person> v;
	Person p1("aaa",10);
	Person p2("bbb",20);
	Person p3("ccc",30);
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	//第一种遍历方法
	vector<Person>::iterator itBegin=v.begin();
	vector<Person>::iterator itEnd=v.end();
	while(itBegin!=itEnd){
		cout<<"姓名:"<<(*itBegin).Name<<" 年龄:"<<(*itBegin).Age<<endl;
		itBegin++;
	}
	//第二种遍历方法
	for(vector<Person>::iterator it=v.begin();it!=v.end();it++){
		cout<<"姓名:"<<(*it).Name<<" 年龄:"<<(*it).Age<<endl;
	}
	//第三种遍历方法
	for_each(v.begin(),v.end(),myPrintPerson);
}

存放自定义数据类型的指针

#include<vector>
#include<algorithm>
#include<string>
class Person{
public:
	string Name;
	int Age;
	Person(string name,int age){
		Name=name;
		Age=age;
	}
}
void myPrintPerson(Person* p){
	cout<<"姓名:"<<p->Name<<" 年龄:"<<p->Age<<endl;
}
void test(){
	vector<Person*> v;
	Person p1("aaa",10);
	Person p2("bbb",20);
	Person p3("ccc",30);
	v.push_back(&p1);
	v.push_back(&p2);
	v.push_back(&p3);
	//第一种遍历方法
	vector<Person*>::iterator itBegin=v.begin();
	vector<Person*>::iterator itEnd=v.end();
	while(itBegin!=itEnd){
		cout<<"姓名:"<<(*itBegin)->Name<<" 年龄:"<<(*itBegin)->Age<<endl;
		itBegin++;
	}
	//第二种遍历方法
	for(vector<Person*>::iterator it=v.begin();it!=v.end();it++){
		cout<<"姓名:"<<(*it)->Name<<" 年龄:"<<(*it)->Age<<endl;
	}
	//第三种遍历方法
	for_each(v.begin(),v.end(),myPrintPerson);
}

vector容器嵌套容器

void test(){
	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);
	//通过v遍历所有元素
	for(vector<vector<int>>::iterator it=v.begin();it!=v.end();it++){//可以将迭代器理解为指针
			for(vector<int> vit=(*it).begin();vit!=(*it).end();vit++){
					cout<<*vit<<" ";
				}	
			cout<<endl;
	}
}

vector构造函数

数组是静态空间,容量固定,vector可以动态扩展(寻找新的空间,将原数据拷贝到新空间,释放原空间)

#include<vector>
void printVector(vector<int>&v){
	for(vector<int>::iterator it=v.begin();it!=v.end();it++){
		cout<<*it<<endl;
	}
}
void test(){
	vector<int>v1;//默认构造
	for(int i=0;i<10;i++){
		v1.push_back(i);
	}
	printVector(v1);
	vector<int>v2(v1.begin(),v1.end());//区间赋值构造
	printVector(v2);
	vector<int>v3(10,100);//10个100
	printVector(v3);
	vector<int>v4(v3);//拷贝构造
	printVector(v4);
}

vector赋值操作

void printVector(vector<int>&v){
	for(vector<int>::iterator it=v.begin();it!=v.end();it++){
		cout<<*it<<endl;
	}
}
void test(){
	vector<int>v1;
	for(int i=0;i<10;i++){
		v1.push_back(i);
	}
	printVector(v1);
	
	vector<int>v2=v1;
	printVector(v2);

	vector<int>v3;
	v3.assign(v1.begin(),v1.end());
	printVector(v3);

	vector<int>v4;
	v4.assign(10,100);//10个100赋值给v4
	printVector(v4);

}

vector容量和大小

void printVector(vector<int>&v){
	for(vector<int>::iterator it=v.begin();it!=v.end();it++){
		cout<<*it<<endl;
	}
}
void test(){
	vector<int>v1;
	for(int i=0;i<10;i++){
		v1.push_back(i);
	}
	printVector(v1);
	if(v1.empty()){
		cout<<"v1是空的"<<endl;	
	}
	else{
		cout<<"v1不为空"<<endl;
		cout<<"v1的容量是:"<<v1.capacity()<<endl;//13
		cout<<"v1的大小是:"<<v1.size()<<endl;//10
	}
	v1.resize(15,10);//重新指定长度,新加的位置用10填充,没有填10默认用0填充
	v1.resize(5);//指定的短,超出部分删除
}

vector插入和删除

void printVector(vector<int>&v){
	for(vector<int>::iterator it=v.begin();it!=v.end();it++){
		cout<<*it<<endl;
	}
}
void test(){
	vector<int>v1;
	for(int i=0;i<10;i++){
		v1.push_back(i);
	}
	printVector(v1);
	v1.pop_back();//删除9
	printVector(v1);
	v1.insert(v1.begin()+2,100);//在v1的第2位插入100
	printVector(v1);
	v1.insert(v1.begin()+1,2,200);//在v1的第1位插入2个200
	printVector(v1);
	v1.erase(v1.begin());
	printVector(v1);
	v1.erase(v1.begin()+2,v1.end()-2);//删除区间位置
	printVector(v1);
	v1.erase(v1.begin(),v1.end());//清空,相当于v1.clear();
	printVector(v1);
}

vector数据存取

void printVector(vector<int>&v){
	for(vector<int>::iterator it=v.begin();it!=v.end();it++){
		cout<<*it<<endl;
	}
}
void test(){
	vector<int>v1;
	for(int i=0;i<10;i++){
		v1.push_back(i);
	}
	for(int i=0;i<v1.size();i++){
		cout<<v1[i]<<endl;//or cout<<v1.at(i)<<endl;
	}
	cout<<"第一个元素为:"<<v1.front()<<endl;
	cout<<"最后一个元素为:"<<v1.back()<<endl;
}

vector互换容器

void printVector(vector<int>&v){
	for(vector<int>::iterator it=v.begin();it!=v.end();it++){
		cout<<*it<<endl;
	}
}
void test(){
	vector<int>v1;
	for(int i=0;i<10;i++){
		v1.push_back(i);
	}
	printVector(v1);
	vector<int>v2;
	for(int i=0;i<10;i++){
		v2.push_back(2*i);
	}
	printVector(v2);
	//交换v1,v2
	v1.swap(v2);
	printVector(v1);
	printVector(v2);
}
void test2(){
	vector<int>v1;
	for(int i=0;i<100000;i++){
		v1.push_back(i);
	}
	cout<<"v1的容量:"<<v1.capacity()<<endl;//138255
	cout<<"v1的大小:"<<v1.size()<<endl;//100000
	v1.resize(3);//重新指定大小
	cout<<"v1的容量:"<<v1.capacity()<<endl;//138255
	cout<<"v1的大小:"<<v1.size()<<endl;//3
	vector<int>(v1).swap(v1);//巧用swap收缩空间,vector<int>(v1)创建匿名对象,与v1互换,运行结束之后匿名对象被回收
	cout<<"v1的容量:"<<v1.capacity()<<endl;//3
	cout<<"v1的大小:"<<v1.size()<<endl;//3

vector预留空间

减少vector在动态扩展时的扩展次数,reserve(int n)预留n个元素长度,预留位置不初始化,元素不可访问

void test(){
	int num=0;//统计内存开辟次数
	int *p=NULL;
	vector<int>v1;
	for(int i=0;i<100000;i++){
		v1.push_back(i);
		if(p!=&v1[0]){
			p=&v1[0];
			num++;
		}
	}
	cout<<num<<endl;//30
	vector<int>v2;
	v2.reserve(100000);
	int num2=0;
	for(int i=0;i<100000;i++){
		v2.push_back(i);
		if(p!=&v2[0]){
			p=&v2[0];
			num2++;
		}
	}
	cout<<num2<<endl;//1
}

string 构造函数

void test(){
	string s1;//默认构造
	const char* str="helloworld";//使用字符串初始化
	string s2(str);
	string s3(s2);//拷贝构造
	string s4(10,'a');//string(n,c);使用n个字符串c初始化
}

string赋值操作

void test(){
	string s1="helloworld";
	cout<<"s1="<<s1<<endl;
	string s2;
	s2=s1;
	string s3='a';
	string s4;
	s4.assign("hello C++");
	string s5;
	s5.assign("hello C++",5);//取前5个字符
	string s6;
	s6.assign(s5);
}

string拼接操作

void test(){
	string s1="helloworld";
	s1+="C++";
	s1+=':';
	string s2="nihao";
	s1+=s2;
	s1.append("I love you");
	s1.append(s2,2);//前2个字符拼接到s2后面去
	s1.append(s2,2,3);//从2开始的3个字符拼接到s2后面去
}

string查找替换操作

void test(){
	string s1="helloworld";
	int pos1=s1.find("ow",1);//从1位置开始找"ow"是否有,如果有返回在s1中的位置,否则返回-1
	int pos1=s1.find("owhell",2,3);//从2位置查找"owhell"的前3个字符是否有,如果有返回在s1中的位置,否则返回-1
	int pos2=s1.rfind("ow");//find从左往右查,rfind从右往左查
	s1.replace(1,2,"123");//从位置1开始的2个位置替换为"123"
}

string字符串比较

void test(){
	string s1="Hello";
	string s2="hello";
	if(s1.compare(s2)==0){
		cout<<"s1=s2"<<endl;}
	else if(s1.compare(s2)>0)
		{
		cout<<"s1>s2"<<endl;
	}
	else{
		cout<<"s1<s2"<<endl;
	}
}

string字符串存取

void test(){
	string s1="hello";
	for(int i=0;i<s1.size();i++){
		cout<<s1[i]<<endl;//or cout<<s1.at(i)<<endl;
	}
	s1[0]='s';
	cout<<s1[0]<<endl;
}

string字符串插入和删除

void test(){
	string s1="hello";
	s1.insert(1,'ex');//hexello
	s1.insert(1,2,'e');//heeexello第1个位置起插入2个'e'
	s.erase(1,2)//从第1个位置起删除2个字符
}

string子串

void test(){
	string s1="hello";
	string s2=s1.substr(1,2);//从第1个位置起截取2个字符
	string email="2040912392490@qq.com";
	int pos=email.find('@');
	string usrname=email.substr(0,pos);//截取QQ号
	cout<<usrname<<endl;
}

deque构造函数

deque内部原理:deque内部有个中控器,维护每段缓冲区中的内容,缓冲区中存放真实数据,中控器维护的是每个缓冲区的地址,使得使用deque时像一片连续的内存空间。
在这里插入图片描述

#include<deque>
void printDeque(const deque<int>& d){
	for(deque<int>::const_iterator it=d.begin();it!=d.end();it++){
		cout<<*it<<" ";//数据不可修改,只读
	}
	cout<<endl;
}
void test(){
	deque<int>d1;
	for(int i=0;i<10;i++){
		d1.push_back(i);	
	}
	printDeque(d1);
	deque<int>d2(d1.begin(),d1.end());//区间赋值
	printDeque(d2);
	deque<int>d3(10,100);//10个100赋值到d3
	printDeque(d3);
	deque<int>d4(d3);//拷贝构造
	printDeque(d4);
}

deque赋值操作

#include<deque>
void printDeque(const deque<int>& d){
	for(deque<int>::const_iterator it=d.begin();it!=d.end();it++){
		cout<<*it<<" ";
	}
	cout<<endl;
}
void test(){
	deque<int>d1;
	for(int i=0;i<10;i++){
		d1.push_back(i);	
	}
	printDeque(d1);
	deque<int>d2;
	d2=d1;
	printDeque(d2);
	deque<int>d3;
	d3.assign(d1.begin(),d1.end());
	printDeque(d3);
	deque<int>d4;
	d4.assign(10,100);
	printDeque(d4);
}

deque大小操作

#include<deque>
void printDeque(const deque<int>& d){
	for(deque<int>::const_iterator it=d.begin();it!=d.end();it++){
		cout<<*it<<" ";
	}
	cout<<endl;
}
void test(){
	deque<int>d1;
	for(int i=0;i<10;i++){
		d1.push_back(i);	
	}
	printDeque(d1);
	if(d1.empty()){
		cout<<"deque是空的"<<endl;}
	else{
		cout<<"deque不是空的"<<endl;
		cout<<"deque的大小是:"<<d1.size()<<endl;//deque没有容量的概念,可以一直放数
		}
	d1.resize(15,1);//指定大小,超过原来的大小,用1补齐
	printDeque(d1);
	d1.resize(5);//超出删除
	printDeque(d1);
}

deque的插入和删除

#include<deque>
void printDeque(const deque<int>& d){
	for(deque<int>::const_iterator it=d.begin();it!=d.end();it++){
		cout<<*it<<" ";
	}
	cout<<endl;
}
void test(){
	deque<int>d1;
	for(int i=0;i<10;i++){
		d1.push_back(i);	//尾插
	}
	printDeque(d1);
	d1.push_front(10);//头插
	printDeque(d1);
	d1.pop_back();//尾删
	printDeque(d1);
	d1.pop_front();//头删
	printDeque(d1);
	d1.insert(d1.begin()+2,1000);//在第2个位置插入1000
	printDeque(d1);
	d1.insert(d1.begin()+1,2,10000);//在第1个位置插入2个10000
	printDeque(d1);
	deque<int>d2;
	d2.push_back(1);
	d2.push_back(2);
	d1.insert(d1.begin(),d2.begin(),d2.end());//在d1第0个位置插入d2上的数
	printDeque(d1);
	d1.erase(d1.begin()+1);//删除一个元素
	d1.erase(d1.begin()+2,d1.end());//区间删除
	d1.clear();//d1清空
}

deque数据存取

#include<deque>
void printDeque(const deque<int>& d){
	for(int i=0;i<d.size();i++){
		cout<<d[i]<<" ";//or cout<<d.at(i)<<" ";
	}
	cout<<endl;
}
void test(){
	deque<int>d1;
	for(int i=0;i<10;i++){
		d1.push_back(i);	//尾插
	}
	printDeque(d1);
	cout<<"访问第一个元素:"<<d1.front()<<endl;
	cout<<"访问最后一个元素:"<<d1.back()<<endl;
}

deque排序

#include<deque>
#include<algorithm>//标准算法头文件
void printDeque(const deque<int>& d){
	for(deque<int>::const_iterator it=d.begin();it!=d.end();it++){
		cout<<*it<<" ";
	}
	cout<<endl;
}
void test(){
	deque<int>d;
	d.push_front(10);
	d.push_front(20);
	d.push_back(100);//20 10 100
	printDeque(d1);
	sort(d1.begin(),d1.end());
	cout<<"排序后:"<<endl;
	printDeque(d1);//默认从小到大排序,对vector和deque等支持随机访问的迭代器的容器都可以用sort排序
}

stack容器的常用接口

栈,先进后出,不允许有遍历行为

#include<stack>
void test(){
	stack<int>s;
	s.push(10);
	s.push(20);
	s.push(30);
	cout<<"栈的大小:"<<s.size()<<endl;
	//只要栈不为空,查看栈顶
	while(!s.empty()){
		cout<<"栈顶元素:"<<s.top()<<endl;
		s.pop();//出栈
	}
	cout<<"栈的大小:"<<s.size()<<endl;
	stack<int>s2(s);//拷贝构造
	stack<int>s3;
	s3=s1;//重载=
}

queue容器的常用接口

队列,先进先出,不允许有遍历行为

#include<queue>
void test(){
	queue<int>q;
	q.push(10);
	q.push(20);
	q.push(30);
	cout<<"队列的大小:"<<q.size()<<endl;
	while(!q.empty()){
		cout<<"队头元素:"<<q.front()<<endl;//查看队头
		cout<<"队尾元素:"<<q.back()<<endl;//查看队尾
		q.pop();//弹出队头元素
	}
	queue<int>q2(q);//拷贝构造
	queue<int>q3;
	q3=q1;//重载=
}

list容器的构造函数

链表,非连续存储结构,每个节点由数据域和指针域组成,支持在任意位置快速插入和删除数据,遍历速度没有数组快,占用空间较数组大。STL的链表是双向循环链表。只支持前移和后移,不能随机访问,属于双向迭代器。

#include<list>
void printList(const list<int>&L){
	for(list<int>::const_iterator it=L.begin();it!=L.end();it++){
		cout<<*it<<" ";
	}
	cout<<endl;
}
void test(){
	list<int>L1;//默认构造
	L1.push_back(10);
	L1.push_back(20);
	L1.push_back(30);
	L1.push_back(40);
	printList(L1);
	list<int>L2(L1.begin(),L1.end());//区间构造
	printList(L2);
	list<int>L3(L2);//拷贝构造
	printList(L3);
	list<int>L4(10,1000);
	printList(L4);
}

list赋值和交换

#include<list>
void printList(const list<int>&L){
	for(list<int>::const_iterator it=L.begin();it!=L.end();it++){
		cout<<*it<<" ";
	}
	cout<<endl;
}
void test(){//赋值
	list<int>L1;
	L1.push_back(10);
	L1.push_back(20);
	L1.push_back(30);
	L1.push_back(40);
	printList(L1);
	list<int>L2=L1;
	printList(L2);
	list<int>L3;
	L3.assign(L2.begin(),L2.end());
	printList(L3);
	list<int>L4;
	L4.assign(10,100);
	printList(L4);
}
void test2(){//交换
	list<int>L1;
	L1.push_back(10);
	L1.push_back(20);
	L1.push_back(30);
	L1.push_back(40);
	cout<<"交换前:"<<endl;
	printList(L1);
	list<int>L2;
	L2.assign(10,100);
	printList(L2);
	cout<<"交换后:"<<endl;
	L1.swap(L2);
	printList(L1);
	printList(L2);
}

list大小操作

#include<list>
void printList(const list<int>&L){
	for(list<int>::const_iterator it=L.begin();it!=L.end();it++){
		cout<<*it<<" ";
	}
	cout<<endl;
}
void test(){//赋值
	list<int>L1;
	L1.push_back(10);
	L1.push_back(20);
	L1.push_back(30);
	L1.push_back(40);
	printList(L1);
	if(L1.empty()){
		cout<<"L1为空"<<endl;
	}else{
		cout<<"L1不为空"<<endl;
		cout<<"L1的元素个数:"<<L1.size()<<endl;
	}
	L1.resize(10,100);//用100填充
	printList(L1);
	L1.resize(2);//删除
	printList(L1);
}

list插入和删除

#include<list>
void printList(const list<int>&L){
	for(list<int>::const_iterator it=L.begin();it!=L.end();it++){
		cout<<*it<<" ";
	}
	cout<<endl;
}
void test(){//赋值
	list<int>L1;
	L1.push_back(10);//尾插
	L1.push_back(20);
	L1.push_back(30);
	L1.push_back(40);
	L1.push_front(100);//头插
	L1.push_front(200);
	L1.push_front(300);
	printList(L1);
	L1.pop_back();//尾删
	L1.pop_front();//头删
	printList(L1);
	L1.insert(++L1.begin(),100);//在第1个位置插入100,不支持L1.begin()+1,只支持L1.begin()++,L1.begin()--,
	//++L1.begin(),--L1.begin()等
	L1.insert(++L1.begin(),10,100);//在第1个位置插入10个100
	list<int>L2;
	L2.push_back(-10);//尾插
	L2.push_back(-20);
	L1.insert(L1.begin(),L2.begin(),L2.end());//区间插入
	printList(L1);
	L1.erase(++L1.begin());//指定位置删除
	printList(L1);
	L1.erase(L1.begin(),L1.end());//区间删除
	L1.push_front(200);
	L1.push_front(200);
	L1.push_front(200);
	L1.remove(200);//删除所有100
	printList(L1);
	L1.clear();
	printList(L1);
}

list数据存取

#include<list>
void printList(const list<int>&L){
	for(list<int>::const_iterator it=L.begin();it!=L.end();it++){
		cout<<*it<<" ";
	}
	cout<<endl;
}
void test(){//赋值
	list<int>L1;
	L1.push_back(10);//尾插
	L1.push_back(20);
	L1.push_back(30);
	L1[0];//错误,不支持随机访问
	L1.at(0);//错误
	cout<<"第一个元素:"<<L1.front()<<endl;
	cout<<"最后一个元素:"<<L1.back()<<endl;
}

list反转和排序

#include<list>
void printList(const list<int>&L){
	for(list<int>::const_iterator it=L.begin();it!=L.end();it++){
		cout<<*it<<" ";
	}
	cout<<endl;
}
bool myCompare(int v1,int v2){
	return v1>v2;//降序从大到小
}
void test(){//赋值
	list<int>L1;
	L1.push_back(10);//尾插
	L1.push_back(20);
	L1.push_back(30);
	cout<<"反转前"<<endl;
	printList(L1);
	cout<<"反转后"<<endl;
	L1.reverse();
	printList(L1);
	cout<<"排序前"<<endl;
	printList(L1);
	cout<<"排序后"<<endl;
	L1.sort();//默认从小到大,sort(L1.begin(),L1.end());错误,只能调用成员函数
	L1.sort(myCompare);
	printList(L1);
}

set/multiset容器构造

关联式容器,底层结构是用二叉树实现
set不允许由重复的元素,multiset允许有重复元素

#include<set>
void printSet(Set::<int>&s){
	for(set<int>::iterator it=s.begin();it!=s.end();it++){
		coout<<*it<<" ";
	}
	cout<<endl;
}
void test(){
	set<int>s1;
	s1.insert(10);//插入数据用insert
	s1.insert(30);
	s1.insert(20);
	s1.insert(30);
	printSet(s1);//10 20 30,元素插入时自动从小到大排序,不允许插入重复值
	set<int>s2(s1);//拷贝构造
	printSet(s2);
	set<int>s3;
	s3=s1;//赋值
	printSet(s3);
}

set大小和交换

#include<set>
void printSet(Set::<int>&s){
	for(set<int>::iterator it=s.begin();it!=s.end();it++){
		coout<<*it<<" ";
	}
	cout<<endl;
}
void test(){
	set<int>s1;
	s1.insert(10);//插入数据用insert
	s1.insert(30);
	s1.insert(20);
	s1.insert(30);
	cout<<"交换前"<<endl;
	printSet(s1);
	if(s1.empty()){
		cout<<"s1是空的"<<endl;
	}else{
		cout<<"s1不是空的"<<endl;
		cout<<"s1的大小是:"<<s1.size()<<endl;
	}
	set<int>s2;
	s2.insert(100);//插入数据用insert
	s2.insert(300);
	s2.insert(200);
	s2.insert(300);
	printSet(s2);
	cout<<"交换后"<<endl;
	s1.swap(s2);
	printSet(s1);
	printSet(s2);
}

set插入和删除

#include<set>
void printSet(Set::<int>&s){
	for(set<int>::iterator it=s.begin();it!=s.end();it++){
		coout<<*it<<" ";
	}
	cout<<endl;
}
void test(){
	set<int>s1;
	s1.insert(10);//插入数据用insert
	s1.insert(30);
	s1.insert(20);
	s1.insert(30);//10 20 30
	printSet(s1);
	s1.erase(s1.begin());//删除 20 30
	printSet(s1);
	s1.erase(30);//直接删除30这个数,得到20
	printSet(s1);
	s1.erase(s1.begin(),s1.end());//区间清空
	printSet(s1);
	s1.insert(30);
	s1.insert(20);
	s1.clear();//清空
	printSet(s1);
}

set查找和统计

#include<set>
void printSet(Set::<int>&s){
	for(set<int>::iterator it=s.begin();it!=s.end();it++){
		coout<<*it<<" ";
	}
	cout<<endl;
}
void test(){
	set<int>s1;
	s1.insert(10);//插入数据用insert
	s1.insert(30);
	s1.insert(20);
	s1.insert(30);//10 20 30
	set<int>::iterator pos=s1.find(30);//找到就返回该位置的迭代器,没找到就返回set.end()
	if(pos!=s1.end()){//find返回迭代器
		cout<<"找到元素"<<*pos<<endl;
	}
	else{
		cout<<"没找到元素"<<endl;
	}
	int num=set.count(30);//统计次数,对set而言统计结果要么1要么0,对multiset统计次数可能大于1
}

set和multiset的区别

set不可以插入重复数据,multiset可以插入重复数据

#include<set>
void printSet(Set::<int>&s){
	for(set<int>::iterator it=s.begin();it!=s.end();it++){
		coout<<*it<<" ";
	}
	cout<<endl;
}
void test(){
	set<int>s1;
	pair<set<int>,bool>res=s.insert(10);//返回值是pair类型
	if(res.second){cout<<"第一次插入成功"<<endl;}//第一次插入成功
	else{cout<<"第一次插入失败"<<endl;}
	res=s.insert(10);
	if(res.second){cout<<"第二次插入成功"<<endl;}
	else{cout<<"第二次插入失败"<<endl;}//第二次插入失败
	multiset<int>ms;
	ms.insert(10);//返回值是iterator
	ms.insert(10);
	for(multiset<int>::iterator it=ms.begin();it!=ms.end();it++){
		cout<<*it<<" ";
}
	cout<<endl;//10 10
}

pair对组创建

成对出现的数据利用对组可以返回两个数据

void test(){
	pair<string,int>p("Tom",20);
	cout<<"姓名:"<<p.first<<" 年龄:"<<p.second<<endl;
	
	pair<string,int>p2=make_pair("Jerry",30);
	cout<<"姓名:"<<p2.first<<" 年龄:"<<p2.second<<endl;
}

set容器排序

#include<set>
class MyCompare{
public:
	bool operator()(int v1, int v2){
		return v1>v2;
	}
}
void test(){
	set<int>s1;
	s1.insert(10);
	s1.insert(20);
	s1.insert(30);
	for(set<int>::iterator it=s1.begin();s1!=end();s1++){
		cout<<*it<<" ";
	}
	cout<<endl;//10 20 30默认从小到大
	//指定排序规则从大到小
	set<int,MyCompare>s2;
	s2.insert(10);
	s2.insert(20);
	s2.insert(30);
	for(set<int>::iterator it=s2.begin();s2!=end();s2++){
		cout<<*it<<" ";
	}
	cout<<endl;//30 20 10	
}

存放自定义数据类型,均需要重载比较函数

#include<string>
#include<set>
class Person{
public:
	Person(string name,int age){
		this->Name=name;
		this->Age=age;
}	
	string Name;
	int Age;
}
class MyCompare{
public:
	bool operator()(const Person& v1, const Person& v2){
		return v1.Age>v2.Age;
	}
}
void test(){
	set<Person,Compare>s1;
	s1.insert(Person('tangseng',10));
	s1.insert(Person('shaseng',20));
	s1.insert(Person('sunwukong',30));
	for(set<Person,Compare>::iterator it=s1.begin();s1!=end();s1++){
		cout<<"姓名:"<<(*it).Name<<" 年龄:"<<(*it).Age<<" ";
	}
	cout<<endl;
}

map和multimap容器

map中的元素都是pair<key,value>,所有元素都根据元素的键值自动排序,底层用二叉树实现。map不允许插入重复key值,multimap允许有重复key值。

#include<map>
void printMap(map<int,int>&m){
	for(map<int,int>::iterator it=m.begin();it!=m.end();it++){
		cout<<"key="<<(*it).first()<<" value="<<(*it).second<<endl;
	}
}
void test(){
	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));
	m.insert(pair<int,int>(4,40));
	printMap(m);//默认按照key从小到大排序
	map<int,int>m2(m);//拷贝构造
	printMap(m2);
	map<int,int>m3;
	m3=m2;//=赋值构造
	printMap(m3);
}

map大小和交换

#include<map>
void printMap(map<int,int>&m){
	for(map<int,int>::iterator it=m.begin();it!=m.end();it++){
		cout<<"key="<<(*it).first()<<" value="<<(*it).second<<endl;
	}
}
void test(){
	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));
	m.insert(pair<int,int>(4,40));
	if(m.empty()){
		cout<<"m为空"<<endl;
	}else{
		cout<<"m不为空"<<endl;
		cout<<"m的大小:"<<m.size()<<endl;
	}
	map<int,int>m2;
	m2.insert(pair<int,int>(-1,10));
	m2.insert(pair<int,int>(-3,30));
	m2.insert(pair<int,int>(-2,20));
	m2.insert(pair<int,int>(-4,40));
	cout<<"交换前:"<<endl;
	printMap(m1);
	printMap(m2);
	m.swap(m2);
	cout<<"交换后:"<<endl;
	printMap(m1);
	printMap(m2);
}

map 插入和删除

#include<map>
void printMap(map<int,int>&m){
	for(map<int,int>::iterator it=m.begin();it!=m.end();it++){
		cout<<"key="<<(*it).first()<<" value="<<(*it).second<<endl;
	}
}
void test(){
	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));
	m.insert(pair<int,int>(4,40));
	m.insert(make_pair(10,20));
	m.insert(map<int,int>::value_type(30,40));//值类型
	m[50]=60;//直接赋值插入,没有赋值时默认value=0
	printMap(m);
	m.erase(m.begin());
	printMap(m);
	m.erase(10);//按照key来删除
	printMap(m);
	m.erase(m.begin(),m.end());
	m.clear();//清空
}

map查找和统计

#include<map>
void printMap(map<int,int>&m){
	for(map<int,int>::iterator it=m.begin();it!=m.end();it++){
		cout<<"key="<<(*it).first()<<" value="<<(*it).second<<endl;
	}
}
void test(){
	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));
	m.insert(pair<int,int>(4,40));
	map<int,int>::iterator pos=m.find(1);
	if(pos!=m.end()){
		cout<<"查到了元素,key="<<(*pos).first<<" value="<<pos->second<<endl;
	}else{
		cout<<"没查到元素"<<endl;
	}
	m.count(1);//输出1或者0,multimap可以大于1
}

map容器排序

#include<map>
void printMap(map<int,int,MyCompare>&m){
	for(map<int,int,MyCompare>::iterator it=m.begin();it!=m.end();it++){
		cout<<"key="<<(*it).first()<<" value="<<(*it).second<<endl;
	}
}
class MyCompare{
public:
	bool operator()(int v1,int v2){
		return v1>v2;//降序
		}
	}
void test(){
	map<int,int,MyCompare>m;
	m.insert(pair<int,int>(1,10));
	m.insert(pair<int,int>(3,30));
	m.insert(pair<int,int>(2,20));
	m.insert(pair<int,int>(4,40));
	printMap(m);//排序按照key从大到小排列
}

STL函数对象

基本概念

重载函数调用操作符的类,其对象常称为函数对象,也叫仿函数,函数对象是一个类,不是函数。

特点:

  • 函数对象在使用时,可以像普通函数那样调用,可以有参数、返回值等
  • 函数对象超出普通函数的概念,可以有自己的状态
  • 函数对象可以作为参数传递
class MyAdd{
public:
	int count;
	MyAdd(){
		this->count=0;
	}
	int operator()(int v1,int v2){
		this->count++;//每次调用count+1
		return v1+v2;
		}
}
void doAdd(MyAdd& ma,int a){
	ma(a,10);
}
void test(){
	MyAdd myadd;
	cout<<"1+2="<<myadd(1,2)<<endl;
	cout<<"加10:"<<doAdd(myadd,20)<<endl;//作为参数传递
}

谓词

仿函数的返回值类型是bool数据类型,称为谓词。
一元谓词

#include<vector>
#include<algorithm>
class GreaterFive{
public:
	bool operator()(int val){//参数个数为1个,称为一元谓词
		return val>5;
	}
}
void test(){
	vector<int>v;
	for(int i=0;i<10;i++){
		v.push_back(i);
	}
	vector<int>::iterator it=find_if(v.begin(),v.end(),GreaterFive());//查找容器中第一个大于5的数字
	if(it==v.end()){cout<<"未找到"<<endl;}
	else{cout<<"找到了,大于0的数:"<<*it <<endl;}
}

二元谓词

#include<vector>
#include<algorithm>
class MyCompare{
public:
	bool operator()(int v1,int v2){//参数个数为2个,称为二元谓词
		return v1>v2;
	}
}
void test(){
	vector<int>v;
	v.push_back(10);
	v.push_back(20);
	v.push_back(30);
	v.push_back(40);//输出结果为10 20 30 40,要求改变排序规则为降序
	sort(v.begin(),v.end(),MyCompare());
	for(vector<int>::iterator it=v.begin();it!=v.end();it++){
		cout<<*it<<" ";//40 30 20 10
	}
	cout<<endl;
}

内建函数对象

分类:

  • 算术仿函数
    在这里插入图片描述
#include<functional>//需要引入头文件
void test(){
	negate<int>n;
	cout<<n(50)<<endl;//取反,-50
	plus<int>p;
	cout<<p(10,10)<<endl;
}
  • 关系仿函数
    在这里插入图片描述
#include<functional>//需要引入头文件
void test(){
	vector<int>v;
	v.push_back(10);
	v.push_back(40);
	v.push_back(30);
	sort(v.begin(),v.end());//升序排列
	sort(v.begin(),v.end(),greater<int>());//降序排序
}
  • 逻辑仿函数
    在这里插入图片描述
#include<functional>//需要引入头文件
#include<algorithm>
void printVector(vector<int>&v){
	for(vector<int>::iterator it=v.begin();it!=v.end();it++){
		cout<<*it<<endl;
	}
}
void test(){
	vector<int>v;
	v.push_back(true);
	v.push_back(false);
	v.push_back(false);
	printVector(v);
	vector<int>v2;
	v2.resize(v.size());//先开辟空间
	transform(v.begin(),v.end(),v2.begin(),logical_not<bool>());//搬运
	printVector(v2);
}

STL常用算法

遍历

for_each遍历容器

#include<algorithm>
void print01(int val ){
	cout<<val<<" ";
}
class print02{//仿函数
public:
	void operator()(int val){
		cout<<val<<" ";
	}
}
void test(){
	vector<int>v;
	for(int i=0;i<10;i++){
		v.push_back(i);
	}
	for_each(v.begin(),v.end(),print01);
	cout<<endl;
	for_each(v.begin(),v.end(),print02());//仿函数需要加()
	cout<<endl;
}

transform搬运容器到另一个容器

#include<algorithm>
class Transform{//仿函数
public:
	int operator()(int val){
		return val+10;
	}
}
class myPrint{//仿函数
public:
	void operator()(int val){
		cout<<val<<" ";
	}
}
void test(){
	vector<int>v;
	for(int i=0;i<10;i++){
		v.push_back(i);
	}
	vector<int>vt;
	vt.resize(v.size());//需要提前开辟空间
	transform(v.begin(),v.end(),vt.begin(),Transform());//搬运数据
	for_each(vt.begin(),vt.end(),myPrint());
}

查找

find查找元素
find_if按条件查找元素
adjacent_find查找相邻重复元素
binary_search二分查找
count统计元素个数
count_if按条件统计元素个数

内置数据类型:

#include<algorithm>
class GreaterFive{
public:
	bool operator()(int val){
		return val>5;
	}
}
void test(){
	vector<int>v;
	for(int i=0;i<10;i++){
		v.push_back(i);
	}
	vector<int>::iterator it=find(v.begin(),v.end(),5);
	if(it==v.end()){cout<<"没有找到"<<endl;}
	else{cout<<"找到"<<*it<<endl;}
	
	vector<int>::iterator iit=find_if(v.begin(),v.end(),GreaterFive());
	if(iit==v.end()){cout<<"没有找到"<<endl;}
	else{cout<<"找到"<<*iit<<endl;}

	v.push_back(9);
	v.push_back(10);
	vector<int>::iterator pos=adjacent_find(v.begin(),v.end());
	if(pos==v.end()){cout<<"没有找到"<<endl;}
	else{cout<<"找到"<<*pos<<endl;}

	bool res=binary_search(v.begin(),v.end(),8);//容器必须是有序序列
	if(res){cout<<"找到了元素"<<endl;}
	else{cout<<"没有找到"<<<<endl;}

	int num=count(v.begin(),v.end(),9);
	cout<<"9有"<<num<<"个"<<endl;

	int num2=count_if(v.begin(),v.end(),GreaterFive());
	cout<<"大于5的元素个数有"<<num2<<"个"<<endl;
}

自定义数据类型:

#include<algorithm>
class Person{
public:
	Person(string name,int age){
		this->Name=name;
		this->Age=age;
	}
	string Name;
	int Age;
	bool operator==(const Person &p){
		if(this->Name==p.Name && this->Age==p.Age){
			return true;
		}
		return false;
	}
}
class Greater20{
public:
	bool operator()(const Person& p){
		return p.Age>20;
	}
}
void test(){
	vector<Person> v;
	Person p1("aaa",10);
	Person p2("bbb",20);
	Person p3("ccc",30);
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	vector<Person>::iterator it=find(v.begin(),v.end(),p1);
	if(it==v.end()){cout<<"没有找到"<<endl;}
	else{cout<<"找到"<<(*it).Name<<endl;}

	vector<Person>::iterator iit=find_if(v.begin(),v.end(),Greater20());
	if(iit==v.end()){cout<<"没有找到"<<endl;}
	else{cout<<"找到"<<(*iit).Name<<endl;}

	v.push_back(p3);
	vector<Person>::iterator pos=adjacent_find(v.begin(),v.end());
	if(pos==v.end()){cout<<"没有找到"<<endl;}
	else{cout<<"找到"<<(*pos).Name<<endl;}

	int num=count(v.begin(),v.end(),p3);//需要重载==
	cout<<"p3有"<<num<<"个"<<endl;

	int num2=count_if(v.begin(),v.end(),Greater20());
	cout<<"大于20岁的人员个位数为"<<num2<<"个"<<endl;
}

排序

sort对容器内元素排序
random_shuffle洗牌,随即调整顺序
merge两容器元素合并存储到另一容器中
reverse反转指定范围的元素

#include <algorithm>
#include<ctime>
class myPrint{//仿函数
public:
	void operator()(int val){
		cout<<val<<" ";
	}
}
void test(){
	srand((unsigned int)time(NULL));//加入随机种子
	vector<int>v;
	for(int i=0;i<10;i++){
		v.push_back(i);
	}
	for_each(v.begin(),v.end(),myPrint());
	cout<<endl;
	random_shuffle(v.begin(),v.end());
	for_each(v.begin(),v.end(),myPrint());
	cout<<endl;
	sort(v.begin().v.end(),greater<int>());//greater内置,从大到小排序
	for_each(v.begin(),v.end(),myPrint());
	cout<<endl;

	vector<int>v2;
	for(int i=0;i<10;i++){
		v2.push_back(10-i);
	}
	vector<int>vt;
	vt.resize(v1.size()+v2.size());
	merge(v1.begin(),v1.end(),v2.begin(),v2.end(),vt.begin());
	for_each(vt.begin(),vt.end(),myPrint());
	cout<<endl;

	reverse(v1.begin(),v1.end());
	for_each(vt.begin(),vt.end(),myPrint());
	cout<<endl;

拷贝和替换

copy容器内指定范围的元素拷贝到另一容器中
replace将容器内指定范围的旧元素改为新元素
replace_if将容器内指定范围满足条件的旧元素改为新元素
swap互换两个同种类型的容器的元素

#include <algorithm>
class myPrint{//仿函数
public:
	void operator()(int val){
		cout<<val<<" ";
	}
}
class GreaterFive{
public:
	bool operator()(int val){
		return val>5;
	}
}
void test(){
	vector<int>v;
	vector<int>v2;
	for(int i=0;i<10;i++){
		v.push_back(i);
	}
	for_each(v.begin(),v.end(),myPrint());
	cout<<endl;
	v2.resize(v.size());
	copy(v.begin(),v.end(),v2.begin());
	for_each(v2.begin(),v2.end(),myPrint());
	cout<<endl;
	replace(v.begin(),v.end(),0,10);//把所有的0替换成10
	for_each(v.begin(),v.end(),myPrint());
	cout<<endl;
	replace_if(v.begin(),v.end(),GreaterFive(),20);//把比5大的数替换为30
	for_each(v.begin(),v.end(),myPrint());
	cout<<endl;
	cout<<"交换前:"<<endl;
	for_each(v.begin(),v.end(),myPrint());
	cout<<endl;
	for_each(v2.begin(),v2.end(),myPrint());
	cout<<endl;
	swap(v,v2);
	cout<<"交换后:"<<endl;
	for_each(v.begin(),v.end(),myPrint());
	cout<<endl;
	for_each(v2.begin(),v2.end(),myPrint());
	cout<<endl;

算术生成

accumulate计算容器元素累计总和
fill向容器中添加元素

#include <numeric>
class myPrint{//仿函数
public:
	void operator()(int val){
		cout<<val<<" ";
	}
}
void test(){
	vector<int>v;
	vector<int>v2;
	for(int i=0;i<10;i++){
		v.push_back(i);
	}
	int total=accumulate(v.begin(),v.end(),0)//0是起始累加值
	cout<<"累加和是:"<<total<<endl;
	v.resize(20);
	fill(v.begin(),v.end(),20);//用20填充其他位置
	for_each(v.begin(),v.end(),myPrint());
	cout<<endl;
}

集合

set_intersection求两个容器的交集
set_union求两个容器的并集
set_difference求两个容器的差集

#include <algorithm>
class myPrint{//仿函数
public:
	void operator()(int val){
		cout<<val<<" ";
	}
}
void test(){
	vector<int>v1;
	vector<int>v2;
	vector<int>vi;
	vector<int>vu;
	vector<int>vd;
	for(int i=0;i<10;i++){
		v1.push_back(i);
		v2.push_back(i+5);
	}
	vi.resize(min(v1.size(),v2.size()));
	vector<int>::iterator itEnd=set_intersection(v1.begin(),v1.end(),v2.begin(),v2.end(),vi.begin());
	//返回最后一个元素的位置
	for_each(vi.begin(),itEnd,myPrint());//5 6 7 8 9
	cout<<endl;

	vu.resize(v1.size()+v2.size());
	vector<int>::iterator itEnd=set_union(v1.begin(),v1.end(),v2.begin(),v2.end(),vu.begin());
	for_each(vu.begin(),itEnd,myPrint());//0 1 2 3 4 5 6 7 8 9
	cout<<endl;

	vd.resize(max(v1.size(),v2.size()));
	vector<int>::iterator itEnd=set_difference(v1.begin(),v1.end(),v2.begin(),v2.end(),vd.begin());//v1-v2
	//求差集的两个集合必须是有序序列
	for_each(vd.begin(),itEnd,myPrint());//0 1 2 3 4 
	cout<<endl;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值