STL意义:在数据结构和算法方面建立一套标准,提高代码复用性。
STL广义分类:容器 算法 迭代器
容器和算法通过迭代器进行无缝连接
STL几乎所有代码都采用模板类或模板函数
STL六大组件:
容器:将各种常用的数据结构实现出来,用来存放数据 vector\list\deque\set\map...
常用数据结构:数组、链表、树、栈、队列、集合、映射表...
序列式容器:强调值的排序,每个元素均有固定的位置
关联式容器:二叉树结构,各元素之间没有严格的顺序关系
算法 Algorithms
质变算法:运算过程中会更改区间内元素的内容 eg 拷贝、删除
非质变算法:运算过程中不会更改区间内元素的内容 eg 查找、计数
迭代器:容器与算法之间的胶合剂。提供一种方法,其能够依序访问某容器所含各个元素,同时 无需暴露容器内部表示方式。
1. 算法要通过迭代器才可以访问容器中元素
2.每个容器都有自己专属的迭代器
3.迭代器行为类似指针,初学时可暂理解为指针
仿函数:重载() 协助算法
适配器:修饰容器、仿函数、迭代器的接口
空间配置器:空间配置和管理
STL初识:
vector存放内置、自定义数据类型
1.vector存放内置数据类型
#include <vector>
//创建vector容器,可看做(整型)数组
vector<int> v;//用尾插法写入两个数据
v.push_back(10);
v.push_back(20);
方法1:
vector<int>::iterator itBegin = v.begin(); //起始迭代器 指向容器中第一个元素
vector<int>::iterator itEnd = v.end(); //结束迭代器 指向容器中最后一个元素的下一个位置
while (itBegin != itEnd)
{
cout << *itBegin << endl;
itBegin++;
}
方法2:将法1做简化
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << endl;
}
方法3:利用vector内置的遍历算法 ,需要利用函数回调,即myPrint函数在for_each中使用时调用
#include<algorithm> //算法头文件
void myPrint(int val) //传入容器的数据是int,因此此处也形参也为int
{
cout<<val<<endl;
}
for_each(v.begin(), v.end(), myPrint);
2.vector存放自定义数据类型
vector<Person> v; 类似
容器嵌套容器
——类比二维数组
大容器中储存小容器,小容器中储存int类型数据
for (vector<vector<int>> ::iterator it = v.begin(); it != v.end(); it++)
{ //*it 的类型是<>内的内容,即小vector容器.因此需要在内层遍历.
for (vector<int> ::iterator vit = (*it).begin(); vit != (*it).end(); vit++)
{ //int类型
cout << *vit << " ";
}
cout << endl;
}
String容器
本质:string是一个类。类内部封装char* 管理这个字符串 是一个char*型容器
1.string的构造函数
函数原型 意义、使用
string() 创建空字符串 string s1;
string(const char* s) 使用字符串s初始化(c风格)
const char* str = "hello world"
string s2(str);
string (const string & str) 拷贝构造 string s3(s2)
string(int n , char c) 使用n个字符c初始化 string s4(10, ‘ a ')
2.string的赋值操作
operator= 赋值 更为常用。
函数原型
string& operator=(const char* s) string s1 = "hello world"
string& operator=(const string & s) string s2 = s1 ;
string& operator=(char c) string s3 = 'a' ;
string& assign(const char* s) s4.assign("hello world")
string& assign(const char* s , int n) s5.assign(s4 , 5) //把s前n个字符赋给当前 字符串
string& assign(const string & s) s6.assign(s5) //拷贝构造
string& assign(int n , char c) s7.assign(5, 'a') //输出5个a
3.string字符串拼接
法一 :operator+= 重载
string str1 = "我";
string& operator+= (const char * s) str1+= "爱玩游戏" //追加多个字符
string& operator+= (const char c) str1 += ' : ' //追加单个字符
string& operator+= (const string & s) str2 = "LOL" ; str1 += str2; //连接另一个字符串
法二:append函数
str3 = " I "
string& append(const char* s) str3.append(" love ")
string& append(const char* s , int n) str3.append("Game abc" , 4)
//拼接s中前4个字符 (Game)
string& append(const string &s) str3.append(str2) //s2接在str3末尾
string& append(const string &s , int pos,int n) str3.append(str2,0,3)
//str2从0号位置开始接入,一共接入3个字符
4.string查找和替换
查找:find函数/ rfind函数
int pos = s1.find(" 字符串 ")
若找到,返回第一个字符的位置; 若未找到,返回 -1
string s1 = "abcde";
int pos = s1.find("de");
if (pos == -1)
{
cout << "未找到该字符串" << endl;
}
else
{
cout << "该字符串于" << pos << "位置找到" << endl;
}
rfind:从右往左查,查到的第一个字符串的位置,返回。
替换:replace函数
s1.replace( 1 , 3 , "1111")
//从1号位置起 3个字符 替换为"1111"
5.string字符串比较 compare函数
利用字符的ASCII码值比较
int a = s1.compare(s2);
s1 = s2 ----------------------- a = 0
s1 > s2 ----------------------- a = 1
s1 < s2 ----------------------- a = -1
6.string字符存取 [] 或 at =函数
读: 读取单个字符
string s1 = "abcde";
for (int i = 0; i < s1.size(); i++)
{
cout << s1[i] << " ";
cout << endl;
}
for (int i = 0; i < s1.size(); i++)
{
cout << s1.at(i) << " ";
cout << endl;
}
写: 修改单个字符
s1[0] = 'x';
s1.at(1) = 'x';
7.string插入和删除
插入 insert函数
删除 erase函数
string s1 = "abcde";
s1.insert(1,"111"); //从1号位置开始 , 插入“111”
//a111bcde
cout << s1;
s1.erase(1, 3); //从1号位置开始,删除3个字符
//abcde
cout << s1;
8.string子串
string s1 = "abcde";
string subStr = s1.substr(1,3); //从1号位置开始,截取3个字符
//bcd
cout << subStr;
实用操作:获取有效信息
//从邮箱截取姓名
void getName()
{
string str1 = " zhangsan@163.com";
int pos = str1.find("@");
string usrName = str1.substr(0, pos);
cout << "姓名为" << usrName;
}
Vector容器
1.基本概念:
和数组非常相似,也称为单端数组(在数组尾端添加/删除)
与数组区别:数组是静态空间,不能扩容,而vector可以动态扩展
动态扩展:找到更大的内存空间,将原数据拷贝到新空间,然后释放原空间。
2.vector构造函数
创建vector容器,可以赋初值
//无参构造
vector<int> v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
//将区间[ v1.begin() , v1.end() ) 传入v2
vector<int> v2(v1.begin() , v1.end());
//传入10个100
vector<int> v3(10,100);
//拷贝构造
vector<int> v4(v3);
3.vector赋值操作
等号赋值
vector<int>v1 = v0;
assign赋值
//区间 [ v0.begin(), v0.end() ) 赋值
vector<int>v2;
v2.assign(v0.begin(), v0.end());//n个 element 赋值
vector<int>v3;
v3.assign(10, 100);
4.vector容量和大小
empty() 判断容器是否为空 返回true/false
capacity() 容器容量 返回int
size() 返回容器中元素的个数(<= 容量)
resize()
resize()
//重新指定容器大小
v1.resize( 10 ) //如果重新指定的比原来要长,默认用0填充新的位置,此时vector发生 动态扩展,新的容量会比10更大一点
v1.resize( 10,100) // 利用参数2可以指定填充新位置的数字,从0变为100
v1.resize( 1 ) //如果重新指定的比原来要短,多余的会被删除,size变小,容量不变
5.vector插入和删除
push_back(ele) 尾插元素ele
insert(const_interator pos , ele) 迭代器指向位置pos插入元素ele
insert(const_interator pos ,int count , ele) 迭代器指向位置pos插入count个元素ele
pop_back(ele) 尾删元素ele
erase(const_interator pos) 删除迭代器指向位置的元素
erase(const_interator start , const_interator end) 删除迭代器从start到end之间的元素
clear() 删除容器中所有元素
6.vector数据存取
v0[1] 返回第1号元素
v0.at(1) 返回第1号元素
v0.front() 返回容器第一个元素(第0号)
v0.back() 返回容器最后一个元素
7.vector互换容器
实现两个容器互换 swap函数
v2.swap(v1)
实际用途:收缩内存空间
当我们resize容器后,size会变小但capacity不会,造成内存的浪费。
创建匿名对象x ,将v1拷贝到x上,此时的v1.size()为2,因此x只会开辟很小的容量。
swap后,v1的容量变为小容量,而匿名对象x在本行代码执行结束后销毁。
vector<int> v1;
for (int i = 0; i < 10000; i++)
{
v1.push_back(i);
}
cout << "v1容量为" << v1.capacity() << endl; //12138
cout << "v1大小为" << v1.size() << endl; //10000
v1.resize(2);//匿名对象
vector<int>(v1).swap(v1);
cout << "v1容量为" << v1.capacity() << endl; //2
cout << "v1大小为" << v1.size() << endl; //2
8.vector预留空间
reserve(int len)
当插入数据比较大时,vector会随着数据插入不断做动态扩展。利用reserve可以提前预留空间,减少动态扩展次数。
vector<int> v1;
int* p = NULL;
int num = 0;
for (int i = 0; i < 10000; i++)
{
v1.push_back(i);
if (p != &v1[0]) //利用动态扩展会找一块新的内存空间的特性,统计动态扩展次数
{
p = &v1[0];
num++;
}
}
cout << num; // 24
提前预留空间后,动态扩展只有初始的1次.
v1.reserve(10000);
cout<<num; // 1
Deque容器
双端数组,可以对头端进行插入删除操作
Deque与Vector:
1.Deque对于头部插入删除的效率高、速度快;
2.Deque访问元素时速度比Vector慢,与二者内部实现有关。Deque容器由中控器 和缓冲区组成,中控器记录不同缓冲区的地址,当现有缓冲区被数据占满时,中 控器指向新的地址,开辟缓冲区,继续储存数据。
1.deque构造函数
deque<int> d1;
deque<int>d2(d1.begin(),d1.end());
deque<int>d3(10,100);
deque<int>d4(d3);
2.deque赋值
d2 = d1;
d3.assign(d1.begin(),d1.end());
d4.assign(10,100);
3.deque大小操作
d1.empty()
d1.size()
d1.resize(num) //若容器变短辟,默认0填充新位置
d1.resize(num, elem) //若容器变长,以elem填充新位置
//deque没有容量的概念
4.deque插入和删除
两端操作:
push_back(num) //尾插
push_front(num) //头插
pop_back() //尾删
pop_front() //头删
指定位置操作:
//用insert要提供迭代器
insert(pos , elem) //在pos位置插入一个elem元素的拷贝,返回新数据的位置
insert(pos , n , elem) // 在pos位置插入n个elem元素的拷贝,无返回值
insert(pos , beg , end) // 在pos位置插入区间[beg , end )的数据,无返回值
clear() //清空
erase(beg,end) //删除区间数据,返回下一个数据的位置
erase(pos) //删除位置上数据,返回下一个数据的位置
5.deque数据存取
d1[int ] //访问第i个元素
d1.at( int )
front() //返回第一个元素
back()
6.deque排序操作
#include<algorithm>
sort(d.begin(),d.end())
默认排序规则:从小到大升序排列
对于支持随机访问的迭代器的容器,都可以用sort算法直接进行排序(如vector)
stack容器
特点:只有一个出口,先进的后出。
栈底密封,栈顶开口,从栈顶进出。
不允许有遍历行为,因为除栈顶处之外的元素外界 访问不到。
类比:挤地铁、弹匣
入栈 push 出栈 pop
stack的常用接口:
push(elem) 入栈
pop() 栈顶元素出栈
empty() 是否为空
size() 栈的大小
queue容器
入队 push
出队 pop
返回队头元素 front
返回队尾元素 back
判断是否为空 empty
返回队列大小 size
list容器 链表
链表由一系列结点组成,而结点由数据域和指针域组成。
数据域储存本结点处元素,指针域储存下一个结点数据的地址。
通过指针实现元素之间的逻辑顺序
list的优点:
动态存储分配,不会造成内存浪费和溢出。(用多少开多少)
执行插入和删除操作很方便,修改指针即可,不需移动大量元素。
list的缺点: 需要的内存空间大,遍历所需的时间长。
list和vector是两个重要的容器,他们的优缺点是互补的。
1.list构造函数
list<int>l1;
l1.push_back(10);
l1.push_back(20);
list<int>l2(l1.begin(), l1.end());
//拷贝构造
list<int>l3(l2);
//10个1000
list<int>l4(10, 1000);
2.list赋值和交换
//operator=
L2 = L1;
//assign
L2.assign(L1.begin(),L1.end());
L3.assign(10,100); //赋值:10个100
swap
L1.swap(L2);
3.list大小操作
//和vector相同
size()
empty()
resize(num)
resize(num,elem)
4.list插入和删除
与之前相同:
push_back(num) //尾插
push_front(num) //头插
pop_back() //尾删
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) //删除区间数据,返回下一个数据的位置
erase(pos) //删除位置上数据,返回下一个数据的位置
新增:
remove(elem) //删除容器中所有与elem值匹配的元素
5.list数据存取
与vector不同!
( [ ] 、 at 不行 , 因为list是链表,不用连续线性空间储存数据,迭代器也不支持随机访问。)
访问第一个元素 front()
访问最后一个元素 back()
技巧:判断容器迭代器的性质
list<int>::iterator it = L1.begin(); //创建迭代器
//支持双向
it++;
it--;
//不报错-->支持随机访问;报错则不支持。(能否跳跃式访问数据)
it = it + 1; it = it + 2...
6.list反转和排序
L.reverse(); //1 2 3 4 5 ----> 5 4 3 2 1
//所有不支持随机访问迭代器的容器,不可以用标准算法
//他们的内部会提供对应的一些算法(成员函数)
//sort(L1.begin(),L1.end()) 错误
L1.sort(); //默认从小到大,升序
//改变排序方式为降序:
bool mycompare(int v2,int v2)
{
return v1 > v2;
}
L1.sort(mycompare)
set/multiset 容器
所有元素会在插入时自动被排序
本质:属于关联式容器,底层用二叉树实现
二者区别:set不允许容器中有重复元素,而multiset允许。
1.set容器构造和赋值
set<int> s1;
set<int>s2(s1);
赋值:
s3 = s2;
2.set大小和交换
set不提供resize
empty();
size();
s2.swap(s1);
3.set插入和删除
插入只有insert一种
插入时会自动排序,默认升序
插入的重复值会被自动忽略
set<int>s1;
s1.insert(10);
s1.insert(5);
s1.insert(100);
s1.insert(5); //无效
erase(pos) //删除pos位置迭代器对应的元素
erase(elem) //删除元素elem
clear(); erase(s.begin(),s.end()) //清空
4.set查找和统计
查找:
set<int>::iterator pos = s1.find(30) //查找set中有没有30,返回的是迭代器
if(pos != s1.end()) //找到了元素,值为*pos = 30
else //未找到
统计:
int num = s1.count(30) //返回容器中30的个数
//对于set容器,值为0或1.(无重复元素)
5.pair 对组的创建
利用对组可以返回两个数据
不用包含头文件
//创建法1
pair<type1,type2> p ( 数据1,数据2)
//创建法2
pair<type1,type2> p2 = make_pair(数据1,数据2)
//访问
p.first ; p.second
6.set容器排序(内置类型)
set容器默认排序规则为从小到大,利用仿函数可以改变排序规则。
class MyCompare { public: bool operator()(int v1,int v2) { return v1 > v2; } }; void test01() { set<int,MyCompare>s1; s1.insert(10); s1.insert(30); s1.insert(20); for (set<int, MyCompare>::iterator it = s1.begin(); it != s1.end(); it++) { cout << *it << " "; } cout << endl; }
7.set容器排序(自定义数据类型)
自定义数据类型放到set容器中,必须利用仿函数指定排序规则,否则编译器不知道怎么处理。
class Person
{
public:
Person(string name, int age)
{
m_Name = name;
m_Age = age;
}
string m_Name;
int m_Age;
};
class ComparePerson
{
bool operator()(const Person &p1,const Person &p2)
{
//按年龄降序
return p1.m_Age > p2.m_Age;
}
};
void test01()
{
set<Person, ComparePerson>s1;
Person p1("张三", 18);
Person p1("李四", 100);
Person p1("王五", 90);
for (set<Person, ComparePerson>::iterator it = s1.begin(); it != s1.end(); it++)
{
cout << (*it).m_Age << " " << (*it).m_Name << endl;
}
}
map/multimap容器(重要)
简介:
map中所有元素都是pair(对组)
pair中第一个元素为key,索引作用;第二个元素为value,实值
所有的元素会按 键值key自动排序(升序)
本质:属于关联式容器,底层结构由二叉树实现
优点:能根据key值快速找到value值
map与multimap:map不允许容器中有重复的key值元素
multimap允许容器中有重复key值元素
二者都允许重复的value值
1.map构造和赋值
默认构造
插入数据时要插入对组pair,因为map容器中存放的元素是对组
map<int, int>m1;
m1.insert(pair<int,int>(1, 10));
m1.insert(pair<int, int>(3, 30));
m1.insert(pair<int, int>(2, 20));
for (map<int, int>::iterator it = m1.begin(); it != m1.end(); it++)
{
cout << (*it).first << " " << it->second << endl;
}
拷贝构造
map<int,int>m2(m1);
赋值
map<int,int>m3;
m3 = m2;
2.map大小和交换
size();
empty();
swap(m);
3.map插入和删除
插入
m.insert(pair<int,int>(1,10));
m.insert(make_pair(2,20));
m[3] = 30; //不建议插数时使用,推荐在访问已有键值对时使用
删除
erase(pos) //pos是迭代器
erase(key); //按照key删除!
erase(beg,end) // 等价于clear()
4.map查找和统计
find(key) //若找到,返回key所在位置迭代器;若未找到,返回end()
map<int, int>::iterator pos = m1.find(3);
if(pos != m.end()) //找到了,key为(*pos).first; value为pos->second
else //没找到
count(key) //统计指定key的个数 ,返回整数
// map,0或1; multimap可能大于1
5.map排序
默认排序是按key值从小到大,利用仿函数改变排序规则
class MyCompare
{
public:
bool operator()(int v1, int v2)
{
return v1 > v2;
}
};
void test01()
{
map<int, int,MyCompare>m1;
m1.insert(make_pair(1, 10));
m1.insert(make_pair(2, 20));
for (map<int, int,MyCompare>::iterator it = m1.begin(); it != m1.end(); it++)
{
cout << (*it).first << " " << it->second << endl;
}
}
案例tips
1. 前面创建好迭代器it,后面for循环使用it时,第一个参数不用填写。
2.可以用count和index来遍历部分容器,减少运算。
multimap<int,Worker>::iterator it = m.find(0);
int index = 0;
int count = m.count(0);
for (; it != m.end() && index < count; it++, index++)
{
cout << it->second.m_Name << " " << it->second.m_Salary << endl;
}
3.用下面这种向函数传入两个容器的方式,可以在遍历A容器的同时给B容器传值(*it)
void setWorker(vector<Worker> &v, multimap<int, Worker>& m)
{
for (vector<Worker>::iterator it = v.begin(); it != v.end(); it++)
{
int deptNum = rand() % 3;
//将员工插入分组
m.insert(make_pair(deptNum, *it));
}
}
函数对象(仿函数)
1.函数对象使用时,可以像普通函数一样调用。可以有参数和返回值。
class MyAdd
{
public:
int operator()(int v1, int v2)
{
return v1 + v2;
}
};
void test01()
{
MyAdd ad;
cout<<ad(10, 20);
}
2.函数对象可以有属于自己的状态
仿函数写在类中,因此可以通过创建类内的变量来描述函数对象的状态。下面例子中,用count记录函数对象调用的次数。
class MyPrint
{
public:
MyPrint()
{
count = 0;
}
void operator()(string text)
{
cout << text << endl;
count++;
}
int count;
};
void test01()
{
MyPrint mp;
mp("Hello World");
mp("Hello World");
mp("Hello World");
cout << mp.count << endl;
}
3.函数对象可以作为参数传递
class MyPrint
{
public:
void operator()(string text)
{
cout << text << endl;
}
};
void doPrint(MyPrint& mp, string text)
{
mp(text);
}
谓词
概念:返回bool类型的仿函数
若operator() 接收一个参数,称为一元谓词;接收两个参数,称为二元谓词。
一元谓词:
class GreaterThanFive
{
public:
bool operator()(int a)
{
return a > 5;
}
};
void test01()
{
vector<int>v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
//匿名对象
vector<int>::iterator it = find_if(v.begin(), v.end(), GreaterThanFive());
if (it != v.end())
{
cout << "找到了,值为" << *it;
}
else
cout << "未找到" << endl;
}
内建函数对象
C++内部别人写好的仿函数,可以直接用。
包含头文件:#include<functional>
1.算数仿函数
negate 取反仿函数
negate<int>p;
p(50); //-50
plus 加法仿函数
plus<int>p; //二元的也只需传入一个int,因为默认相加二者类型相同
p(10,20); //30
minus 减法
multiples 乘法
divides 除法
modulus 取模
2.关系仿函数
上文实现了改变sort函数排序规则:
class MyCompare
{
public:
bool operator()(int v1, int v2)
{
return v1 > v2;
}
};
sort(v.begin(),v.end(),MyCompare())
而利用内置关系仿函数greater,可以快速实现,不用自己写仿函数。
sort(v.begin(),v.end(),greater<int>())
其他关系仿函数:(不常用)
bool equal_to<T> //等于 equal_to<int>()
bool not_equal_to<T>
bool greater_equal<T> //大于等于
bool less<T>
bool less_equal<T>
3.逻辑仿函数(开发中几乎用不到)
bool logical_and<T> () //与
bool logical_or<T> () //或
bool logical_not<T> () //非
STL常用算法
1.遍历
for_each
for_each(v.begin(),v.end(),print01) //普通函数
for_each(v.begin(),v.end(),print02()) //仿函数
transform 搬运容器到另一个容器中
a. 搬运前要先给目标容器开辟空间
b. _Func可以是仿函数也可以是普通函数,其意义在于可以实现搬运同时修改数据
v2.resize(v1.size());
transform(v1.begin(), v1.end(), v2.begin(), _Func);
2.查找
find 查找指定元素,找到返回指定元素迭代器,找不到返回结束迭代器
find(iterator beg,iterator end,value)
注意:查找自定义类型数据时,需要在类内重载==(如下)
bool operator==(const Person&p)
{
if(//.............)
{
return true;
}
}
find_if 按条件查找元素
find_if(iterator beg,iterator end, _Pred) //_Pred 函数或者谓词,作为条件
class GreaterThanFive
{
public:
bool operator()(int a)
{
return a > 5;
}
};
vector<int>::iterator it = find_if(v.begin(),v.end(),GreaterThanFive())
注意:查找自定义类型数据时,需要在类内重载==
adjacent_find 查找相邻且重复元素
adjacent_find(iterator begin,iterator end)
若找到,返回第一个元素的迭代器;若未找到,返回end()
binary_search 查找指定元素是否存在
bool binary_search(iterator beg,iterator end,value)
查到,返回TRUE;否则返回FALSE
容器必须是有序序列(底层用二叉树实现)
count 统计元素个数
count(iterator beg,iterator end,value)
返回元素个数 int类型
统计自定义类型时,重载==(转到定义,可以明白原理)
count_if 按条件统计元素个数
count_if(iterator begin,iterator end, _Pred) _Pred 函数或谓词 作为条件
返回元素个数 int类型
3.排序
sort 普通排序
sort(iterator begin,iterator end) 或 sort(iterator begin,iterator end , _Pred)
不填谓词,默认从小到大排序。
random_shuffle 洗牌 指定范围内元素随即调整顺序
random_shuffle(iterator begin,iterator end)
使用时,加入随机数种子,变为真随机。srand((unsigned int)time(NULL))
merge 两个容器元素合并,并存储到另一个容器中
merge(iterator beg1,iterator end1,iterator beg2,iterator end2, iterator dest)
//最后一个参数是目标容器起始迭代器
两个待合并容器必须是有序的,合并后的容器也将是有序的。
需要提前给目标容器分配空间 v.resize(v1.size() + v2.size())
reverse 将容器内元素反转
reverse(iterator beg,iterator end) 1 2 3 4 5 ------------> 5 4 3 2 1
4. 拷贝和替换
copy 将元素拷贝到另一个容器中
copy(iterator beg,iterator end,iterator dest)
另一个容器也要提前分配空间 v2.resize(v1,size())
replace 指定范围内所有旧元素替换为新元素
replace(iterator beg,iterator end , oldvalue , newvalue)
replace_if 区间范围内满足条件的元素替换为新元素
replace(iterator beg,iterator end , _Pred , newvalue)
swap 互换两个容器的元素
同种类型容器
swap(容器1,容器2)
5.算数生成算法 #include<numeric>
accumulate 计算容器中数据之和
accumulate(iterator beg, iterator end , num) //num是起始累加值
fill 向容器中填充指定元素
fill( iterator beg,iterator end , num) //num为填充值
6.集合算法
set_intersection 求两个容器的交集
两个集合必须是有序序列
提前给目标容器开辟空间 考虑极限情况: vTarget.resize(min(v1.size(),v2.size()))
vector<int>::iterator itEnd = set_intersection(v1.begin(),v1.end(),v2.begin(),v2.end(),vTarget.begin())
返回值是交集结束位置迭代器,用itEnd接收。
遍历时:for_each(vTarget.begin() , itEnd , myPrint()) 若用vTarget.end() 则后面可能会有若干个0
set_union 求两个容器并集
两个集合必须是有序序列
提前给目标容器开辟空间 考虑极限情况: vTarget.resize(v1.size() + v2.size())
vector<int>::iterator itEnd =
set_union(v1.begin(),v1.end(),v2.begin(),v2.end(),vTarget.begin())
返回值是并集结束位置迭代器,用itEnd接收。
遍历时:for_each(vTarget.begin() , itEnd , myPrint()) 若用vTarget.end() 则后面可能会有若干个0
set_difference 求两个容器差集
V1和V2的差集:V1中和V2不相交的部分
V2和V1的差集:V2中和V1不相交的部分
提前给目标容器开辟空间 考虑极限情况: vTarget.resize(max ( v1.size() , v2.size() ) )
vector<int>::iterator itEnd =
set_difference(v1.begin(),v1.end(),v2.begin(),v2.end(),vTarget.begin())
返回值是差集 结束位置迭代器,用itEnd接收。