C++进阶编程
- 范型编程,模板
- STL(标准模板库)常用容器
- vector存放标准数据类型
- vector存放自定义数据类型
- vector容器嵌套容器
- vector构造函数
- vector赋值操作
- vector容量和大小
- vector插入和删除
- vector数据存取
- vector互换容器
- vector预留空间
- string 构造函数
- string赋值操作
- string拼接操作
- string查找替换操作
- string字符串比较
- string字符串存取
- string字符串插入和删除
- string子串
- deque构造函数
- deque赋值操作
- deque大小操作
- deque的插入和删除
- deque数据存取
- deque排序
- stack容器的常用接口
- queue容器的常用接口
- list容器的构造函数
- list赋值和交换
- list大小操作
- list插入和删除
- list数据存取
- list反转和排序
- set/multiset容器构造
- set大小和交换
- set插入和删除
- set查找和统计
- set和multiset的区别
- pair对组创建
- set容器排序
- map和multimap容器
- map大小和交换
- map 插入和删除
- map查找和统计
- map容器排序
- STL函数对象
- STL常用算法
范型编程,模板
目的:建立通用的模具,提高复用性
- 模板不可以直接使用,它只是一个框架
- 模板的通用性并不是万能的
函数模板
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;
}