C++之STL
STL概述
STL(Standard Template Library,标准模板库)
STL的6大组件:容器、算法、迭代器、适配器、仿函数、空间配置
容器:存放数据
算法:操作数据
迭代器:算法 通过迭代器 操作容器
适配器:为算法 提供更多的接口
仿函数:为算法 提供策略
空间配置:为算法、容器提供动态空间
算法分类:质变算法、非质变算法
质变算法:会更改容器的值(拷贝,替换,删除等等)
非质变算法:是指运算过程中不会更改区间内的元素内容,例如查找、计数、遍历、寻找极值等等
容器
string容器
1、stirng的构造函数和赋值
1、stirng的构造函数:
string();//创建一个空的字符串 例如: string str;
string(const string& str);//使用一个string对象初始化另一个string对象
string(const char* s);//使用字符串s初始化
string(int n, char c);//使用n个字符c初始化 v
2、string基本赋值操作
string& operator=(const char* s);//char*类型字符串 赋值给当前的字符串
string& operator=(const string &s);//把字符串s赋给当前的字符串
string& operator=(char c);//字符赋值给当前的字符串
string& assign(const char *s);//把字符串s赋给当前的字符串
string& assign(const char *s, int n);//把字符串s的前n个字符赋给当前的字符串
string& assign(const string &s);//把字符串s赋给当前字符串
string& assign(int n, char c);//用n个字符c赋给当前字符串
string& assign(const string &s, int start, int n);//将s从start开始n个字符赋值给字符串
eg:
int main()
{
//string(const char* s);//使用字符串s初始化
string str("hello");
//string(const string& str);//使用一个string对象初始化另一个string对象
string str2=string(str);
//string(int n, char c);//使用n个字符c初始化 v
string h=string(5,'H');//HHHHH
// string& operator=(const char* s);//char*类型字符串 赋值给当前的字符串
str="world";
//string& operator=(const string &s);//把字符串s赋给当前的字符串
str=str2;
//string& operator=(char c);//字符赋值给当前的字符串
str='A';
//string& assign(const char *s);//把字符串s赋给当前的字符串
str.assign("hello");
//string& assign(const char *s, int n);//把字符串s的前n个字符赋给当前的字符串
str.assign("hello",3);
//string& assign(const string &s);//把字符串s赋给当前字符串
str.assign(str2);
//string& assign(int n, char c);//用n个字符c赋给当前字符串
h.assign(5,'H');
//string& assign(const string &s, int start, int n);//将s从start开始n个字符赋值给字符串
str.assign(str2,0,5);
return 0;
}
2、string存取字符操作
char& operator[](int n);//通过[]方式取字符
char& at(int n);//通过at方法获取字符
string str("hello");
cout<<str[1]<<endl;//e
cout<<str.at(1)<<endl;//e
两者区别:[] 越界不会抛出异常 ,at越界会抛出异常
try
{
//str1[1000]='A';
str1.at(1000)='A';
}
catch(exception &e)
{
cout<<"捕获到异常:"<<e.what()<<endl;
}
3、string拼接操作
string& operator+=(const string& str);//重载+=操作符
string& operator+=(const char* str);//重载+=操作符
string& operator+=(const char c);//重载+=操作符
string& append(const char *s);//把字符串s连接到当前字符串结尾
string& append(const char *s, int n);//把字符串s的前n个字符连接到当前字符串结尾
string& append(const string &s);//同operator+=()
string& append(const string &s, int pos, int n);//把字符串s中从pos开始的n个字符连接到当前字符串结尾
string& append(int n, char c);//在当前字符串结尾添加n个字符c
4、string查找和替换
int find(const string& str, int pos = 0) const; //查找str第一次出现位置,从pos开始查找
int find(const char* s, int pos = 0) const; //查找s第一次出现位置,从pos开始查找
int find(const char* s, int pos, int n) const; //从pos位置查找s的前n个字符第一次位置
int find(const char c, int pos = 0) const; //查找字符c第一次出现位置
int rfind(const string& str, int pos = npos) const;//查找str最后一次位置,从pos开始查找
int rfind(const char* s, int pos = npos) const;//查找s最后一次出现位置,从pos开始查找
int rfind(const char* s, int pos, int n) const;//从pos查找s的前n个字符最后一次位置
int rfind(const char c, int pos = 0) const; //查找字符c最后一次出现位置
string& replace(int pos, int n, const string& str); //替换从pos开始n个字符为字符串str
string& replace(int pos, int n, const char* s); //替换从pos开始的n个字符为字符串s
5、string比较操作
> < == != 运算符 可用
/*
compare函数在>时返回 1,<时返回 ‐1,==时返回 0。
比较区分大小写,比较时参考字典顺序,排越前面的越小。
大写的A比小写的a小。
*/
int compare(const string &s) const;//与字符串s比较
int compare(const char *s) const;//与字符串s比较
6、提取string子串
string substr(int pos = 0, int n = npos) const;
//返回由pos开始的n个字符组成的字符串 pos是起始位置,n是长度
void test06()
{
string str1="hehehe:hahaha:xixixi:lalala";
int pos = 0;
while(1)
{
int ret = str1.find(":", pos);
string tmp = str1.substr(pos, ret‐pos);
cout<<tmp<<endl;
pos = ret+1;
}
}
7、string插入和删除操作
string& insert(int pos, const char* s); //插入字符串
string& insert(int pos, const string& str); //插入字符串string& insert(int pos, int n, char c);//在指定位置插入n个字符c
string& erase(int pos, int n = npos);//删除从Pos开始的n个字符
#include <iostream>
#include<string>
using namespace std;
int main()
{
string str="hello";
str.insert(2,"###");//he###llo
cout<<str<<endl;
str.erase(2,3);//hello
cout<<str<<endl;
return 0;
}
8、 string和c-style字符串转换
string str="hello"; //char * => string (认支持)
char *h=str; //string => char * 报错
string转换成char* 必须使用成员函数c_str(c_str的返回值是const char *)
char *h=(char *)str.c_str();//强转,将const char *转成char*
char *h2=const_cast<char *>(str.c_str());
vector容器
单端动态数组容器
push_back尾部插入元素、pop_back尾部删除元素
front()头元素、back()尾元素
begin()得到的是 容器的 起始迭代器(首元素的位置)
end() 得到的是 结束迭代器(尾元素的下一个元素位置
必须包含头文件:#include<vector>
#include <iostream>
#include<vector>
using namespace std;
int main()
{
vector<int> v1;
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
v1.push_back(40);
//遍历容器
vector<int>::iterator it=v1.begin();//定义一个迭代器iterator 保存是元素的位置
for(;it!=v1.end();it++){
cout<<*it<<endl;
}
return 0;
}
vector的未雨绸缪机制:
#include <iostream>
#include<vector>
using namespace std;
int main()
{
vector<int> v;
cout<<"容量:"<<v.capacity()<<" "<<"大小:"<<v.size()<<endl;
vector<int>::iterator it;
int i=0;
int count=0;
for(i=1;i<=1000;i++){
v.push_back(1);
if(it!=v.begin()){
count++;
cout<<"第"<<count<<"开辟空间,容量为:"<<v.capacity()<<endl;
it=v.begin();
}
}
return 0;
}
容量:0 大小:0
第1开辟空间,容量为:1
第2开辟空间,容量为:2
第3开辟空间,容量为:4
第4开辟空间,容量为:8
第5开辟空间,容量为:16
第6开辟空间,容量为:32
第7开辟空间,容量为:64
第8开辟空间,容量为:128
第9开辟空间,容量为:256
第10开辟空间,容量为:512
第11开辟空间,容量为:1024
vector API
vector构造函数:
vector<T> v; //采用模板实现类实现,默认构造函数
vector(v.begin(), v.end());//将v[begin(), end())区间中的元素拷贝给本身。
vector(n, elem);//构造函数将n个elem拷贝给本身。
vector(const vector &vec);//拷贝构造函数
vector常用赋值操作
assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem);//将n个elem拷贝赋值给本身。
vector& operator=(const vector &vec);//重载等号操作符
swap(vec);// 将vec与本身的元素互换。
vector大小操作:
size();//返回容器中元素的个数
empty();//判断容器是否为空
resize(int num);//重新指定容器的长度为num,若容器变长,则以默认值0填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
resize(int num, elem);//重新指定容器的长度为num,若容器变长,则以elem值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
capacity();//容器的容量
reserve(int len);//容器预留len个元素长度,预留位置不初始化,元素不可访问
vector数据存取操作
at(int idx); //返回索引idx所指的数据,如果idx越界,抛out_of_range异常。
operator[];//返回索引idx所指的数据,越界时,运行直接报错
front();//返回容器中第一个数据元素
back();//返回容器中最后一个数据元素
vector插入和删除操作
insert(const_iterator pos, int count,ele);//迭代器指向位置pos插入count个元素ele.
push_back(ele); //尾部插入元素ele
pop_back();//删除最后一个元素
erase(const_iterator start, const_iterator end);//删除迭代器从start到end之间的元素
erase(const_iterator pos);//删除迭代器指向的元素
clear();
巧用swap收缩空间:
int main()
{
vector<int> v1;
v1.reserve(1000);//预留1000个空间
v1.assign(5,10);//存入5个10
cout<<"大小:"<<v1.size()<<"容量:"<<v1.capacity()<<endl;
vector<int>(v1).swap(v1);//拷贝构造一个和v1一样的匿名vector,再和v1交换
cout<<"大小:"<<v1.size()<<"容量:"<<v1.capacity()<<endl;
return 0;
}
大小:5容量:1000
大小:5容量:5
容器嵌套容器
int main()
{
vector<int> v1(5,10);
vector<int> v2(5,100);
vector<int> v3(5,1000);
vector<vector<int>> v;
v.push_back(v1);
v.push_back(v2);
v.push_back(v3);
//遍历
vector<vector<int>>::iterator mit;
for(mit=v.begin();mit!=v.end();mit++){
vector<int>::iterator it;
for(it=(*mit).begin();it!=(*mit).end();it++){
cout<<*it<<" ";
}
cout<<endl;
}
return 0;
}
打印结果
10 10 10 10 10
100 100 100 100 100
1000 1000 1000 1000 1000
使用算法 对 vector容器排序
需要引入算法的头文件
#include<algorithm>
#include <iostream>
#include<vector>
#include<algorithm>
using namespace std;
void printVectorInt(vector<int> v){
vector<int>::iterator it;
for(it=v.begin();it!=v.end();it++){
cout<<*it<<endl;
}
}
bool myCompare(int a,int b){
return a<b;
}
int main()
{
vector<int> v1;
v1.push_back(20);
v1.push_back(60);
v1.push_back(30);
v1.push_back(50);
v1.push_back(40);
v1.push_back(10);
printVectorInt(v1);
cout<<"------------"<<endl;
// sort(v1.begin(),v1.end());
//sort(v1.begin(),v1.end(),greater<int>());//greater从大到小排序
sort(v1.begin(),v1.end(),myCompare);
printVectorInt(v1);
return 0;
}
vector存放自定义数据类型
#include <iostream>
#include<vector>
#include<algorithm>
using namespace std;
class Person{
friend void printVectorPerson(vector<Person> v);
friend bool myCompare(const Person &ob1,const Person &ob2);
private:
int num;
string name;
float score;
public:
Person(){}
Person(int num,string name,float score){
this->num=num;
this->name=name;
this->score=score;
}
//重载小于号
bool operator<(const Person &p){
return this->num<p.num;
}
};
void printVectorPerson(vector<Person> v){
vector<Person>::iterator it;
for(it=v.begin();it!=v.end();it++){
cout<<(*it).num<<" "<<(*it).name<<" "<<(*it).score<<endl;
}
}
bool myCompare(const Person &ob1,const Person &ob2){
return ob1.num>ob2.num;
}
int main()
{
vector<Person> v;
v.push_back(Person(100, "lucy", 88.8f));
v.push_back(Person(103, "bob", 99.8f));
v.push_back(Person(103, "tom", 77.8f));
v.push_back(Person(103, "德玛", 88.8f));
v.push_back(Person(101, "小法", 66.8f));
printVectorPerson(v);
cout<<"------------"<<endl;
sort(v.begin(),v.end());
printVectorPerson(v);
cout<<"------------"<<endl;
sort(v.begin(),v.end(),myCompare);
printVectorPerson(v);
return 0;
}
100 lucy 88.8
103 bob 99.8
103 tom 77.8
103 德玛 88.8
101 小法 66.8
------------
100 lucy 88.8
101 小法 66.8
103 bob 99.8
103 tom 77.8
103 德玛 88.8
------------
103 bob 99.8
103 tom 77.8
103 德玛 88.8
101 小法 66.8
100 lucy 88.8
deque容器
deque:双端动态数组
deque容器和vector容器最大的差异,
一在于deque允许使用常数项时间对头端进行元素的插入和删除操作。
二在于deque没有容量的概念
deque的API
如果迭代器能+1 那么该迭代器为随机访问迭代器
1、deque构造函数;
deque<T> deqT;//默认构造形式
deque(beg, end);//构造函数将[beg, end)区间中的元素拷贝给本身。
deque(n, elem);//构造函数将n个elem拷贝给本身
deque(const deque &deq);//拷贝构造函数。
2、deque赋值操作
assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem);//将n个elem拷贝赋值给本身。
deque& operator=(const deque &deq); //重载等号操作符
swap(deq);// 将deq与本身的元素互换
3、deque大小操作
deque.size();//返回容器中元素的个数
deque.empty();//判断容器是否为空
deque.resize(num);//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
deque.resize(num, elem); //重新指定容器的长度为num,若容器变长,则以elem值填充新位置,如果容器变短,则末尾超出容器长度的元素被删除。
4、deque双端插入和删除操作
push_back(elem);//在容器尾部添加一个数据
push_front(elem);//在容器头部插入一个数据
pop_back();//删除容器最后一个数据
pop_front();//删除容器第一个数据
5、deque数据存取
at(idx);//返回索引idx所指的数据,如果idx越界,抛出out_of_range。
operator[];//返回索引idx所指的数据,如果idx越界,不抛出异常,直接出错。
front();//返回第一个数据。
back();//返回最后一个数据。
6、deque插入操作
insert(pos,elem);//在pos位置插入一个elem元素的拷贝,返回新数据的位置。
insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值。
insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。
7、deque删除操作
clear();//移除容器的所有数据
erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。
erase(pos);//删除pos位置的数据,返回下一个数据的位置
stack容器
stack是一种先进后出(First In Last Out,FILO)的数据结构
操作数据的一端 叫栈顶。
top永远指向栈顶元素。
栈容器没有迭代器。不支持遍历行为。
1、stack构造函数
stack<T> stkT;//stack采用模板类实现, stack对象的默认构造形式:
stack(const stack &stk);//拷贝构造函数
2、stack赋值操作
stack& operator=(const stack &stk);//重载等号操作符
3、stack数据存取操作
push(elem);//向栈顶添加元素
pop();//从栈顶移除第一个元素
top();//返回栈顶元素
4、stack大小操作
empty();//判断堆栈是否为空
size();//返回堆栈的大小
queue容器
Queue是一种先进先出(First In First Out,FIFO)的数据结构
出数据的一方叫队头,入数据的一方叫队尾。
queue容器没有迭代器 不支持遍历行为。
1、queue的构造函数
queue<T> queT;//queue采用模板类实现,queue对象的默认构造形式:
queue(const queue &que);//拷贝构造函数
2、queue存取、插入和删除操作
push(elem);//往队尾添加元素
pop();//从队头移除第一个元素
back();//返回最后一个元素
front();//返回第一个元素
3、 queue赋值操作
queue& operator=(const queue &que);//重载等号操作符
4、queue大小操作
empty();//判断队列是否为空
size();//返回队列的大小
list容器
list是双向循环链表
list容器的迭代器是 双向迭代器。
1、list构造函数
list<T> lstT;//list采用采用模板类实现,对象的默认构造形式:
list(beg,end);//构造函数将[beg, end)区间中的元素拷贝给本身。
list(n,elem);//构造函数将n个elem拷贝给本身。
list(const list &lst);//拷贝构造函数。
2、list数据元素插入和删除操作
push_back(elem);//在容器尾部加入一个元素
pop_back();//删除容器中最后一个元素
push_front(elem);//在容器开头插入一个元素
pop_front();//从容器开头移除第一个元素
insert(pos,elem);//在pos位置插elem元素的拷贝,返回新数据的位置。
insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值。
insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。
clear();//移除容器的所有数据
erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。
erase(pos);//删除pos位置的数据,返回下一个数据的位置。
remove(elem);//删除容器中所有与elem值匹配的元素
3、list大小操作
size();//返回容器中元素的个数
empty();//判断容器是否为空
resize(num);//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
resize(num, elem);//重新指定容器的长度为num,若容器变长,则以elem值填充新位置。 如果容器变短,则末尾超出容器长度的元素被删除。
4、list赋值操作
assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem);//将n个elem拷贝赋值给本身。
list& operator=(const list &lst);//重载等号操作符
swap(lst);//将lst与本身的元素互换。
5、list数据的存取
front();//返回第一个元素。
back();//返回最后一个元素。
6、list反转排序
reverse();//反转链表,比如lst包含1,3,5元素,运行此方法后,lst就包含5,3,1元素。
sort(); //list排序(因为list支持双向迭代器,所以sort()不支持list,所以list有自带的sort方法)
// lists.sort(greater<int>());从大到小
list<int> l1;
l1.push_back(10);
l1.push_back(20);
l1.push_back(30);
l1.push_front(40);
l1.push_front(50);
l1.push_front(60);
printListInt(l1);//60 50 40 10 20 30
//list容器 是双向迭代器 不支持+2 支持++
list<int>::iterator it=l1.begin();
it++;
it++;
l1.insert(it, 3, 100);
printListInt(l1);//60 50 100 100 100 40 10 20 30
set/multiset容器
set容器只有键值,在插入数据的时候 自动根据键值排序。不允许有相同的键值。不能修改set容器的元素值,会破坏set的数据结构。set容器的迭代器是只读迭代器(const_iterator)
1、set构造函数
set<T> st;//set默认构造函数:
mulitset<T> mst; //multiset默认构造函数:
set(const set &st);//拷贝构造函数
2、set赋值操作
set& operator=(const set &st);//重载等号操作符
swap(st);//交换两个集合容器
3、set大小操作
size();//返回容器中元素的数目
empty();//判断容器是否为空
4、set插入和删除操作
insert(elem);//在容器中插入元素。
clear();//清除所有元素
erase(pos);//删除pos迭代器所指的元素,返回下一个元素的迭代器。
erase(beg, end);//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
erase(elem);//删除容器中值为elem的元素
1、set容器默认排序
void printIntSet(set<int> &li){
set<int>::iterator it;
for(it=li.begin();it!=li.end();it++){
cout<<*it<<" ";
}
cout<<endl;
}
int main(){
set<int> s1;
s1.insert(10);
s1.insert(40);
s1.insert(20);
s1.insert(30);
s1.insert(50);
printIntSet(s1);//10 20 30 40 50
}
2、通过仿函数更改set容器排序规则
class MyDesc{
public:
bool operator()(int v1,int v2) const{ //c++17需要添加const修饰
return v1>v2;
}
};
//需要重载 void printIntSet
void printIntSet(set<int,MyDesc> &li){
set<int>::iterator it;
for(it=li.begin();it!=li.end();it++){
cout<<*it<<" ";
}
cout<<endl;
}
int main(){
//通过仿函数更改set容器排序规则
// set<int,排序规则> s;
set<int,MyDesc> s2;
s2.insert(10);
s2.insert(40);
s2.insert(20);
s2.insert(30);
s2.insert(50);
printIntSet(s2);//10 20 30 40 50
}
3、如果set容器存放自定义数据 必须更改排序规则
#include <iostream>
#include <set>
#include <string>
using namespace std;
class Person{
friend class MyCompare;
friend ostream& operator<<(ostream &out,Person p);
private:
int num;
string name;
float score;
public:
Person(){}
Person(int num,string name,float score){
this->num=num;
this->name=name;
this->score=score;
}
};
//重写输出运算符
ostream& operator<<(ostream &out,Person p){
out<<p.num<<" "<<p.name<<" "<<p.score<<" ";
return out;
}
class MyCompare{
public:
bool operator()(Person p1,Person p2)const{
return p1.num<p2.num;
}
};
void printPersonSet(set<Person,MyCompare> s){
set<Person,MyCompare>::iterator it;
for(it=s.begin();it!=s.end();it++){
cout<<(*it)<<" ";
}
cout<<endl;
}
int main(){
set<Person,MyCompare> s3;
s3.insert(Person(100, "lucy", 88.8f));
s3.insert(Person(103, "bob", 99.8f));
s3.insert(Person(103, "tom", 77.8f));
s3.insert(Person(103, "德玛", 88.8f));
s3.insert(Person(101, "小法", 66.8f));
printPersonSet(s3);//100 lucy 88.8 101 小法 66.8 103 bob 99.8
}
1、set的find和count函数
int main(){
set<int> s1;
s1.insert(10);
s1.insert(40);
s1.insert(20);
s1.insert(30);
s1.insert(50);
printIntSet(s1);//10 20 30 40 50
set<int>::const_iterator ret;
ret=s1.find(50);
if(ret!=s1.end()){
cout<<"找到元素"<<*ret<<endl;
}
cout<<s1.count(50)<<endl;//count的结果只能是0或1,因为set容器的key不能重复
}
2、set的equal和range函数
lower_bound(keyElem);//返回第一个key>=keyElem元素的迭代器。
upper_bound(keyElem);//返回第一个key>keyElem元素的迭代器。
equal_range(keyElem);//返回容器中key与keyElem相等的上下限的两个迭代器,equal_range的返回值是一个pair对组
int main()
{
set<int> s1;
s1.insert(10);
s1.insert(40);
s1.insert(20);
s1.insert(30);
s1.insert(50);
set<int>::iterator ret;
ret=s1.lower_bound(35);//ret>=35
cout<<"下限为:"<<*ret<<endl;//40
ret=s1.upper_bound(35);//ret>35
cout<<"上限为:"<<*ret<<endl;//40
pair<set<int>::iterator,set<int>::iterator> p;//equal_range的返回值是对组,第一个值存放>=,第二个值存放>
p=s1.equal_range(50);
if(p.first!=s1.end()){
cout<<"下限为:"<<*(p.first)<<endl;
}
if(p.second!=s1.end()){
cout<<"上限为:"<<*(p.second)<<endl;
}
return 0;
}
multiset容器:键值允许重复,而set容器的键值不允许重复
int main()
{
set<int> s;
pair<set<int>::iterator,bool> ret;
ret=s.insert(10);
if(ret.second==true){
cout<<"第一次插入成功"<<endl;
}
else{
cout<<"第一次插入失败"<<endl;
}
ret=s.insert(10);
if(ret.second==true){
cout<<"第二次插入成功"<<endl;
}
else{
cout<<"第二次插入失败"<<endl;
}
return 0;
}
void printAll(multiset<int> &s){
multiset<int>::iterator it;
for(it=s.begin();it!=s.end();it++){
cout<<*it<<" ";
}
cout<<endl;
}
int main()
{
multiset<int> s;
s.insert(10);
s.insert(10);
s.insert(20);
printAll(s);//10 10 20
return 0;
}
对组pair
对组(pair)将一对值组合成一个值,这一对值可以具有不同的数据类型,两个值
可以分别用pair的两个公有属性first和second访问
int main()
{
//1、方式一
pair<int,string> p1(10086,"移动");
pair<int,string> p2(10010,"联通");
cout<<p1.first<<','<<p1.second<<endl;
//2、方式二(推荐)
pair<int,string> p4=make_pair(10000,"电信");
cout<<p4.first<<','<<p4.second<<endl;
return 0;
}
map容器/multimap容器
每个元素都是 键值-实值 成对存储,自动根据键值排序, 键值不能重复,不能
修改
1、map构造函数
map<T1, T2> mapTT;//map默认构造函数:
map(const map &mp);//拷贝构造函数
2、map赋值操作
map& operator=(const map &mp);//重载等号操作符
swap(mp);//交换两个集合容器
3、map大小操作
size();//返回容器中元素的数目
empty();//判断容器是否为空
4、map插入数据元素操作
map.insert(...); //往容器插入元素,返回pair<iterator,bool>
map<int, string> mapStu;
// 第一种 通过pair的方式插入对象
mapStu.insert(pair<int, string>(3, "小张"));
// 第二种 通过pair的方式插入对象
mapStu.inset(make_pair(‐1, "校长"));
// 第三种 通过value_type的方式插入对象
mapStu.insert(map<int, string>::value_type(1, "小李"));
// 第四种 通过数组的方式插入值
mapStu[3] = "小刘";
mapStu[5] = "小王";
5、map删除操作
clear();//删除所有元素
erase(pos);//删除pos迭代器所指的元素,返回下一个元素的迭代器。
erase(beg,end);//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
erase(keyElem);//删除容器中key为keyElem的对组。
6、map查找操作
find(key);//查找键key是否存在,若存在,返回该键的元素的迭代器;/若不存在,返回map.end();
count(keyElem);//返回容器中key为keyElem的对组个数。对map来说,要么是0,要么是1。对multimap来说,值可能大于1。
lower_bound(keyElem);//返回第一个key>=keyElem元素的迭代器。
upper_bound(keyElem);//返回第一个key>keyElem元素的迭代器。
equal_range(keyElem);//返回容器中key与keyElem相等的上下限的两个迭代器
示例:
#include <iostream>
#include <map>
#include <string>
using namespace std;
class Person{
friend void printAll(map<int,Person> &m);
friend int main();
private:
int num;
string name;
float score;
public:
Person(){}
Person(int num,string name,float score){
this->num=num;
this->name=name;
this->score=score;
}
};
void printAll(map<int,Person> &m){
map<int,Person>::iterator ret;
for(ret=m.begin();ret!=m.end();ret++){
cout<<(*ret).second.num<<" "<<(*ret).second.name<<(*ret).second.score<<endl;
}
}
int main()
{
map<int,Person> m;
//方式1
m.insert(pair<int,Person>(103,Person(103,"lucy",88.8f)));
//方式2
m.insert(make_pair(101,Person(101,"bob",77.7f)));
//方式3
m.insert(map<int,Person>::value_type(102,Person(102,"tom",66.6f)));
//方式4
m[104] = Person(104,"德玛", 99.9f);
printAll(m);
//查找key为103的元素
map<int,Person>::const_iterator ret;
ret=m.find(103);
if(ret!=m.end()){
cout<<"找到key=103:";
cout<<(*ret).second.num<<" "<<(*ret).second.name<<(*ret).second.score<<endl;
}
return 0;
}
multimap:键值可以重复的map
容器选择
算法
函数对象
函数对象:重载了函数调用运算符()的类,实例化的对象叫做函数对象
函数对象+() 触发 重载函数调用运算符执行 ==>类似函数调用 (仿函数)
class Print{
public:
void operator()(char *str){
cout<<str<<endl;
}
};
int main()
{
Print ob;
ob("hello world");
//等同于
Print()("hello");
}
如果函数对象 有一个参数 叫:一元函数对象
如果函数对象 有二个参数 叫:二元函数对象
如果函数对象 有三个参数 叫:多元函数对象
谓词
返回值为bool类型的普通函数或仿函数都叫谓词。
如果谓词有一个参数 叫:一元谓词
如果谓词有二个参数 叫:二元谓词
1、一元谓词
一元谓词用于查找
#include <iostream>
#include<vector>
#include<algorithm>//find_if
using namespace std;
//普通函数作为一元谓词
bool greaterThan30(int value){
return value>30;
}
//仿函数作为一元谓词
class GreaterThan30{
public:
bool operator()(int value){
return value>30;
}
};
#include<algorithm>
int main()
{
vector<int>v1;
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
v1.push_back(40);
vector<int>::iterator ret;
//找到大于30的
// ret=find_if(v1.begin(),v1.end(),greaterThan30);//普通函数写函数名即可
//仿函数要带上()
ret=find_if(v1.begin(),v1.end(),GreaterThan30());
if(ret!=v1.end()){
cout<<"寻找的结果"<<*ret<<endl;
}
return 0;
}
2、二元谓词
二元谓词用于排序
#include <iostream>
#include<vector>
#include <algorithm>
using namespace std;
void printAll(vector<int> v){
vector<int>::iterator it;
for(it=v.begin();it!=v.end();it++){
cout<<*it<<" ";
}
cout<<endl;
}
/**
* 普通函数
*/
bool myGreaterInt(int v1,int v2){
return v1>v2;
}
/**
*
* 仿函数
*/
class MyGreaterInt{
public:
bool operator()(int v1,int v2){
return v1>v2;
}
};
int main()
{
vector<int>v1;
v1.push_back(10);
v1.push_back(30);
v1.push_back(20);
v1.push_back(35);
printAll(v1);
//sort(v1.begin(),v1.end(),myGreaterInt);//普通函数
sort(v1.begin(),v1.end(),MyGreaterInt());//仿函数
printAll(v1);
return 0;
}
内建函数对象
就是系统提供好的函数对象
1、6个算数类函数对象,除了negate是一元运算,其他都是二元运算。
template<class T> T plus<T>//加法仿函数
template<class T> T minus<T>//减法仿函数
template<class T> T multiplies<T>//乘法仿函数
template<class T> T divides<T>//除法仿函数
template<class T> T modulus<T>//取模仿函数
template<class T> T negate<T>//取反仿函数
2、6个关系运算类函数对象,每一种都是二元运算。
template<class T> bool equal_to<T>//等于
template<class T> bool not_equal_to<T>//不等于
template<class T> bool greater<T>//大于
template<class T> bool greater_equal<T>//大于等于
template<class T> bool less<T>//小于
template<class T> bool less_equal<T>//小于等于
3、逻辑运算类运算函数,not为一元运算,其余为二元运算。
template<class T> bool logical_and<T>//逻辑与
template<class T> bool logical_or<T>//逻辑或
template<class T> bool logical_not<T>//逻辑非
int main()
{
vector<int>v1;
v1.push_back(10);
v1.push_back(30);
v1.push_back(20);
v1.push_back(35);
printAll(v1);
sort(v1.begin(),v1.end(),greater<int>());//使用内建函数对象
printAll(v1);
return 0;
}
之前的find_if也可以用内建函数对象
#include <iostream>
#include<vector>
#include<algorithm>//find_if
using namespace std;
int main()
{
vector<int>v1;
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
v1.push_back(40);
v1.push_back(50);
vector<int>::iterator ret;
// ret=find_if(v1.begin(),v1.end(),greaterThan30);//普通函数写函数名即可
// ret=find_if(v1.begin(),v1.end(),GreaterThan30());
//使用内置
ret=find_if(v1.begin(),v1.end(),bind2nd(greater<int>(),30));
if(ret!=v1.end()){
cout<<"寻找的结果"<<*ret<<endl;
}
return 0;
}
适配器
适配器为算法提供接口。
1、仿函数作为适配器
#include <iostream>
#include<vector>
#include<algorithm>//find_if
using namespace std;
//2:公共继承 binary_function参数萃取
class printInt:public binary_function<int,int,void>{
public:
//3、整个函数加const修饰
void operator()(int value,int tmp) const{
cout<<"value="<<value<<" "<<"tmp="<<tmp<<endl;
}
};
int main()
{
vector<int>v1;
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
v1.push_back(40);
v1.push_back(50);
//1、bind2nd或者bind1st, bind2nd将100绑定都第二个参数tmp行 容器的元素在value上
for_each(v1.begin(),v1.end(),bind2nd(printInt(),100));
return 0;
}
2、普通函数作为适配器ptr_fun
/*
普通函数
*/
void myPrintInt(int value,int tmp){
cout<<"value="<<value<<"tmp="<<tmp<<endl;
}
int main()
{
vector<int>v1;
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
v1.push_back(40);
v1.push_back(50);
//使用ptr_fun转换
for_each(v1.begin(),v1.end(),bind2nd(ptr_fun(myPrintInt),100));
return 0;
}
3、成员函数作为适配器 mem_fun_ref
#include <iostream>
#include<vector>
#include<algorithm>//find_if
using namespace std;
class Person{
private:
int data;
public:
Person(){}
Person(int d){
data=d;
}
void printPerson(int tmp){
cout<<"data="<<data<<" "<<"tmp"<<tmp<<endl;
}
};
int main()
{
vector<Person>v1;
v1.push_back(Person(10));
v1.push_back(Person(15));
v1.push_back(Person(30));
v1.push_back(Person(20));
v1.push_back(Person(50));
for_each(v1.begin(),v1.end(),bind2nd(mem_fun_ref(&Person::printPerson),10));
return 0;
}
打印结果:
data=10 tmp10
data=15 tmp10
data=30 tmp10
data=20 tmp10
data=50 tmp10
4、取反适配器
①not1 一元取反
vector<int>v1;
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
vector<int>::iterator ret;
ret=find_if(v1.begin(),v1.end(),not1(bind2nd(greater<int>(),10)));//>10取反<=10
if(ret!=v1.end()){
cout<<*ret<<endl;//10
}
②not2 二元取反
vector<int>v1;
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
vector<int>::iterator ret;
sort(v1.begin(),v1.end(),not2(greater<int>()));//从大到小排序取反 从小到大
vector<int>::iterator it;
for(it=v1.begin();it!=v1.end();it++){
cout<<*it<<endl;
}
lambda表达式
vector<int>v1;
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
//lambda表达式c++11才支持
//[]里面啥都不写 lambda不能识别外部数据
//[=]lambda能对外部数据 读操作
//[&]lambda能对外部数据 读写操作
for_each(v1.begin(),v1.end(),[](int val){
cout<<val<<endl;
});
int a=10;
for_each(v1.begin(),v1.end(),[=](int val){
cout<<val<<"a="<<a<<endl;//能够读取外部数据a
});
for_each(v1.begin(),v1.end(),[&](int val){
a=100;//能够修改外部数据a
});
cout<<"a="<<a<<endl;//a=100
常见遍历算法
1、for_each遍历算法
/*
遍历算法 遍历容器元素
@param beg 开始迭代器
@param end 结束迭代器
@param _callback 函数回调或者函数对象
@return 函数对象
*/
for_each(iterator beg, iterator end, _callback);
2、transform算法
transform算法 将指定容器区间元素搬运到另一容器中
@param beg1 源容器开始迭代器
@param end1 源容器结束迭代器
@param beg2 目标容器开始迭代器
@param _cakkback 回调函数或者函数对象
@return 返回目标容器迭代器
*/
transform(iterator beg1, iterator end1, iterator beg2, _callbakc);
实例:
#include <iostream>
#include<vector>
#include<algorithm>
using namespace std;
void printAll(vector<int> v){
vector<int>::iterator it;
for(it=v.begin();it!=v.end();it++){
cout<<*it;
}
cout<<endl;
}
//将传递过来的数据直接返回,不做任何操作
int myTransInt(int val){
return val;//val是遍历v的数据
}
int main()
{
vector<int>v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
vector<int>v2;
//注意 : transform 不会给目标容器分配内存,所以需要我们提前分配好内存
v2.resize(v.size());
transform(v.begin(),v.end(),v2.begin(),myTransInt);
printAll(v2);
return 0;
}
常见查找算法
1、find算法 查找元素
/*
find算法 查找元素
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param value 查找的元素
@return 返回查找元素的位置
*/
find(iterator beg, iterator end, value)
①查找基本类型数据
int main()
{
vector<int>v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
vector<int>::iterator ret;
ret=find(v.begin(),v.end(),30);
if(ret!=v.end()){
cout<<"查找到元素"<<*ret<<endl;
}
return 0;
}
②查找自定义数据类型
查找自定义数据类型 需要重载==
class Person{
friend int main();
private:
int num;
string name;
public:
Person(){}
Person(int num,string name){
this->num=num;
this->name=name;
}
bool operator==(const Person &ob){
return (this->num==ob.num)&&(this->name==ob.name);
}
};
int main()
{
vector<Person> v2;
v2.push_back(Person(10,"bob"));
v2.push_back(Person(20,"tom"));
v2.push_back(Person(30,"lucy"));
vector<Person>::iterator ret;
ret=find(v2.begin(),v2.end(),Person(10,"bob"));
if(ret!=v2.end()){
cout<<"查找到元素"<<(*ret).num<<(*ret).name<<endl;
}
return 0;
}
2、find_if算法 条件查找
int main()
{
vector<int>v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
// vector<Person> v2;
// v2.push_back(Person(10,"bob"));
// v2.push_back(Person(20,"tom"));
// v2.push_back(Person(30,"lucy"));
vector<int>::iterator ret;
ret=find_if(v.begin(),v.end(),bind2nd(greater<int>(),20));
if(ret!=v.end()){
cout<<"查找到元素"<<(*ret)<<endl;
}
return 0;
}
3、adjacent_find算法 查找相邻重复元素
/*
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param _callback 回调函数或者谓词(返回bool类型的函数对象)
@return 返回相邻元素的第一个位置的迭代器
*/
adjacent_find(iterator beg, iterator end, _callback);
int main()
{
vector<int>v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(30);
vector<int>::iterator ret;
ret=adjacent_find(v.begin(),v.end());
if(ret!=v.end()){
cout<<"查找到第一个相邻重复元素"<<(*ret)<<endl;//30
}
return 0;
}
4、binary_search算法 二分查找法
注意: 在无序序列中不可用
int main()
{
vector<int>v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(30);
v.push_back(15);
vector<int>::iterator ret;
sort(v.begin(),v.end());
//注意返回值是bool类型
bool result=binary_search(v.begin(),v.end(),30);
if(result){
cout<<"查找到元素"<<endl;
}
else{
cout<<"没找到元素"<<endl;
}
return 0;
}
5、count算法 统计元素出现次数
/*
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param value
@return int返回元素个数
*/
count(iterator beg, iterator end, value);
int main()
{
vector<int>v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(30);
v.push_back(15);
vector<int>::iterator ret;
int c=count(v.begin(),v.end(),30);
cout<<c<<endl;//2
return 0;
}
6、count_if算法 统计元素出现次数
int main()
{
vector<int>v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(30);
v.push_back(15);
vector<int>::iterator ret;
//统计大于10的元素个数a
int c=count_if(v.begin(),v.end(),bind2nd(greater<int>(),10));//4
cout<<c<<endl;
return 0;
}
常见排序算法
1、merge算法 容器元素合并
/*
merge算法 容器元素合并,并存储到另一容器中
注意:两个容器必须是有序的
@param beg1 容器1开始迭代器
@param end1 容器1结束迭代器
@param beg2 容器2开始迭代器
@param end2 容器2结束迭代器
@param dest 目标容器开始迭代器
*/
merge(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)
void printAll(vector<int> v){
vector<int>::iterator it;
for(it=v.begin();it!=v.end();it++){
cout<<*it<<" ";
}
cout<<endl;
}
int main()
{
vector<int>v1;
v1.push_back(10);
v1.push_back(30);
v1.push_back(50);
v1.push_back(70);
vector<int>v2;
v2.push_back(20);
v2.push_back(40);
v2.push_back(60);
v2.push_back(80);
vector<int>v;
v.resize(v1.size()+v2.size());
merge(v1.begin(),v1.end(),v2.begin(),v2.end(),v.begin());
printAll(v);
return 0;
}
打印输出
10 20 30 40 50 60 70 80
2、sort算法 容器元素排序
/*
sort算法 容器元素排序
@param beg 容器1开始迭代器
@param end 容器1结束迭代器
@param _callback 回调函数或者谓词(返回bool类型的函数对象)
*/
sort(iterator beg, iterator end, _callback)
3、random_shuffle算法 对指定范围内的元素随机调整次序
int main()
{
vector<int>v1;
v1.push_back(10);
v1.push_back(30);
v1.push_back(50);
v1.push_back(70);
srand(time(NULL));//添加随机种子
random_shuffle(v1.begin(),v1.end());
printAll(v1);
return 0;
}
4、reverse算法 反转指定范围的元素
/*
reverse算法 反转指定范围的元素
@param beg 容器开始迭代器
@param end 容器结束迭代器
*/
reverse(iterator beg, iterator end)
常见拷贝替换算法
1、copy算法
/*
copy算法 将容器内指定范围的元素拷贝到另一容器中
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param dest 目标起始迭代器
*/
copy(iterator beg, iterator end, iterator dest)
int main()
{
vector<int>v1;
v1.push_back(10);
v1.push_back(30);
v1.push_back(50);
v1.push_back(70);
vector<int>v2;
v2.resize(v1.size());
copy(v1.begin(),v1.end(),v2.begin());
printAll(v2);
return 0;
}
copy的进阶用法:
遍历vector容器打印元素
#include <iostream>
#include<vector>
#include<algorithm>
#include<iterator>
using namespace std;
int main()
{
vector<int>v1;
v1.push_back(10);
v1.push_back(30);
v1.push_back(50);
v1.push_back(70);
//#include<iterator>
copy(v1.begin(),v1.end(),ostream_iterator<int>(cout," "));
return 0;
}
2、replace算法
/*
replace算法 将容器内指定范围的旧元素修改为新元素
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param oldvalue 旧元素
@param oldvalue 新元素
*/
replace(iterator beg, iterator end, oldvalue, newvalue)
int main()
{
vector<int>v1;
v1.push_back(10);
v1.push_back(30);
v1.push_back(50);
v1.push_back(70);
replace(v1.begin(),v1.end(),30,3000);//将30替换成3000
copy(v1.begin(),v1.end(),ostream_iterator<int>(cout," "));
return 0;
}
输出结果:
10 3000 50 70
3、 replace_if算法
/*
replace_if算法 将容器内指定范围满足条件的元素替换为新元素
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param callback函数回调或者谓词(返回Bool类型的函数对象)
@param oldvalue 新元素
*/
replace_if(iterator beg, iterator end, _callback, newvalue)
class GreaterThan30{
public:
bool operator()(int val){
return val>30;
}
};
int main()
{
vector<int>v1;
v1.push_back(10);
v1.push_back(30);
v1.push_back(50);
v1.push_back(70);
replace_if(v1.begin(),v1.end(),GreaterThan30(),3000);//将>30替换成3000
copy(v1.begin(),v1.end(),ostream_iterator<int>(cout," "));
return 0;
}
4、swap算法
/*
swap算法 互换两个容器的元素
@param c1容器1
@param c2容器2
*/
swap(container c1, container c2)
常用算数生成算法
1、accumulate算法 计算容器元素累计总和
需要引入头文件#include<numeric>
/*
2 accumulate算法 计算容器元素累计总和
3 @param beg 容器开始迭代器
4 @param end 容器结束迭代器
5 @param value累加值 (注意:求和完后 + value)
6 */
7 accumulate(iterator beg, iterator end, value)
#include <iostream>
#include<vector>
#include<algorithm>
#include <string>
#include<iterator>
#include<numeric>
using namespace std;
int main()
{
vector<int>v1;
v1.push_back(10);
v1.push_back(30);
v1.push_back(50);
v1.push_back(70);
//#include<numeric>
int all=accumulate(v1.begin(),v1.end(),0);
cout<<all<<endl;
copy(v1.begin(),v1.end(),ostream_iterator<int>(cout," "));
return 0;
}
2、fill算法 向容器中添加元素
/*
fill算法 向容器中添加元素
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param value t填充元素
*/
fill(iterator beg, iterator end, value)
int main()
{
vector<int>v1;
v1.resize(5);
fill(v1.begin(),v1.end(),5);
copy(v1.begin(),v1.end(),ostream_iterator<int>(cout," "));
return 0;
}
输出结果:
5 5 5 5 5
如果v1中有元素
int main()
{
vector<int>v1;
v1.resize(5);
v1.push_back(10);
v1.push_back(30);
v1.push_back(50);
fill(v1.begin(),v1.end(),5);
copy(v1.begin(),v1.end(),ostream_iterator<int>(cout," "));
return 0;
}
打印结果:
5 5 5 5 5 5 5 5
常用集合算法
1、set_intersection求两个set集合的交集
/*
set_intersection算法 求两个set集合的交集
注意:两个集合必须是有序序列
@param beg1 容器1开始迭代器
@param end1 容器1结束迭代器
@param beg2 容器2开始迭代器
@param end2 容器2结束迭代器
@param dest 目标容器开始迭代器
@return 目标容器的最后一个元素的迭代器地址
*/
set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2,iterator dest)
int main()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(3);
v1.push_back(5);
v1.push_back(7);
v1.push_back(9);
vector<int> v2;
v2.push_back(7);
v2.push_back(9);
v2.push_back(11);
v2.push_back(13);
v2.push_back(15);
vector<int> v3;//存放交集
v3.resize( min(v1.size(), v2.size()));
vector<int>::iterator ret;
// return目标容器的最后一个元素的迭代器地址
ret = set_intersection(v1.begin(), v1.end(), v2.begin(),v2.end(), v3.begin());
copy(v3.begin(), ret, ostream_iterator<int>(cout, " ") );
cout<<endl;
return 0;
}
输出结果
7 9
2、 set_union算法 求两个set集合的并集
/*
set_union算法 求两个set集合的并集
注意:两个集合必须是有序序列
@param beg1 容器1开始迭代器
@param end1 容器1结束迭代器
@param beg2 容器2开始迭代器
@param end2 容器2结束迭代器
@param dest 目标容器开始迭代器
@return 目标容器的最后一个元素的迭代器地址
*/
set_union(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)
int main()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(3);
v1.push_back(5);
v1.push_back(7);
v1.push_back(9);
vector<int> v2;
v2.push_back(7);
v2.push_back(9);
v2.push_back(11);
v2.push_back(13);
v2.push_back(15);
vector<int> v3;//存放交集
v3.resize( v1.size()+v2.size());
vector<int>::iterator ret;
ret = set_union(v1.begin(), v1.end(), v2.begin(),v2.end(), v3.begin());
copy(v3.begin(), ret, ostream_iterator<int>(cout, " ") );
cout<<endl;
// copy(v1.begin(),v1.end(),ostream_iterator<int>(cout," "));
return 0;
}
输出结果:
1 3 5 7 9 11 13 15
3、set_difference算法 求两个set集合的差集
/*
set_difference算法 求两个set集合的差集
注意:两个集合必须是有序序列
@param beg1 容器1开始迭代器
@param end1 容器1结束迭代器
@param beg2 容器2开始迭代器
@param end2 容器2结束迭代器
@param dest 目标容器开始迭代器
@return 目标容器的最后一个元素的迭代器地址
*/
set_difference(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)
int main()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(3);
v1.push_back(5);
v1.push_back(7);
v1.push_back(9);
vector<int> v2;
v2.push_back(7);
v2.push_back(9);
v2.push_back(11);
v2.push_back(13);
v2.push_back(15);
vector<int> v3;//存放交集
v3.resize(v1.size());//求A差B size就设置成A ,求B差A size结果就设置成B
vector<int>::iterator ret;
ret = set_difference(v1.begin(), v1.end(), v2.begin(),v2.end(), v3.begin());
copy(v3.begin(), ret, ostream_iterator<int>(cout, " ") );
cout<<endl;
// copy(v1.begin(),v1.end(),ostream_iterator<int>(cout," "));
return 0;
}