目录
一、STL的概述
1、概述
//STL是由 容器、迭代器、空间适配器、适配器、算法、仿函数六大组件组成;
//STL包含了诸多在计算机科学领域里常用的基本数据机构和基本算法;并且降低了他们之间的耦合关系。
//STL是由惠普实验室开发的一系列软件的统称,现在主要应用于c++中。
2、特点
1.将数据结构和算法分离
2.不需要关心具体的实现过程,只要熟练使用STL就可以。
3.STL具有高度的可重用性,高性能,高移植性,跨平台
3、string 类
//不是STL容器,但是与STL容器有相似之处。
1. 是一个字符串类型,通常用来标识字符串
2.string和插入*的区别
1> string是一个类,char*是一个指向字符串的指针
2> string封装了char*,管理整个字符串,是一个char*的容器
3> string几乎不需要考虑内存越界和内存释放。
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int main(int argc, char const *argv[])
{
#if 0
string s1; //无参构造函数
string s2("helloworld"); //有参构造函数
string s3(10,'a'); //10个a
string s4(s2);
cout<<s1<<endl;
cout<<s2<<endl;
cout<<s3<<endl;
cout<<s4<<endl;
cin>>s1; //重载了输入运算符
cout<<s1<<endl;
s1 += "hellworld";
if(s1 == s2)
{
}
s1 = s1 + s2;
cout<<s1<<endl;
//string的存取
string s("helloworld");
cout<<s[1]<<endl; //重载了下标运算符
s[1] = 'x';
cout << s<<endl;
cout<<s.at(1)<<endl; //通过成员函数来访问
//cout<<s[200000]<<endl; //越界访问会抛出异常
try
{
cout<<s.at(12)<<endl;
}
catch(const std::exception& e)
{
std::cerr << e.what() << '\n';
}
// string的c_str
char buf[32] = {0};
string s("helloworld");
strcpy(buf,s.c_str()); //将s 通过c_str() 转化为 char * ;才能与 char *buf 拷贝;
cout<<buf<<endl;
//string 的copy
char buf[32] = {0};
string s("helloworld");
s.copy(buf,5); //第三个参数是 拷贝目的地,拷贝的个数,开始位置
cout<< buf<<endl;
memset(buf,0,sizeof(buf));
s.copy(buf,4,5); //从第5个字符开始,拷贝 4 个字符进入 buf;
cout<<buf<<endl;
//string的长度 : legth()
string s("helloworld");
cout<<s.length()<<endl;
if(s.empty())
{
cout<<"字符串是空"<<endl;
}
else
{
cout<<"字符串不为空"<<endl;
}
//string的赋值
string s1("helloworld");
s1 = "hello"; //重载了=号运算符
cout<<s1<<endl;
const char *s = "this is test";
s1.assign(s); //将s 赋值给 s1;
cout<<s1<<endl;
s1.assign(s,7); //把字符串s的前7个字符赋值给当前的字符串
cout<< s1<<endl;
s1.assign(5,'a');
cout<<s1<<endl;
string s2("hey boy");
s1.assign(s2); //将s2对象赋值给s1
cout<<s1<<endl;
s1.assign(s2,4,3); //从第四个开始的3个字符赋值给当前字符串
cout<<s1<<endl;
//string的链接
string s1("helloworld");
s1 += "1234";
cout<<s1<<endl;
string s2("abcdefg");
s1 += s2;
cout<< s1<<endl;
const char *s = "hahahah";
s1.append(s); //将s 连接到s1 后面
cout<<s1<<endl;
s1.append(s,2); //将s 的前两个字符拼接到s1的后面
cout<<s1<<endl;
s1.append(s2);
cout<<s1<<endl;
s1.append(s2,4,2); //将第4个字符 的后面两个字符,连接到s2 后面
cout<<s1<<endl;
s1.append(10,'x'); //在第10个 后面连接x
cout<<s1<<endl;
//string的比较
string s1("helloworld");
string s2("helloboy");
const char *s = "hellogirl";
if(s1.compare(s2) > 0) //s1 与 s2 比较
{
cout<<"s1 > s2"<<endl;
}
if(s1.compare(s) > 0)
{
cout<<"s1> s2"<<endl;
}
//string字符串
string s("helloworld");
cout<<s.substr()<<endl; //字符串输出
cout<<s.substr(5,5)<<endl; //将第5个 后面的 5个 字符输出
//string的查找和替换
int p; //位置
string s1("helloworld");
string s2("world");
p = s1.find('o'); //返回的是位置
cout<<p<<endl;
p = s1.find('o',5);
cout<<p<<endl;
p = s1.find('x'); //找不到,返回-1
cout<<p<<endl;
p = s1.find("ll");
cout<<p<<endl;
p = s1.find(s2);
cout<<p<<endl;
p = s1.rfind('o');
cout<<p<<endl;
s1.replace(5,5,"xxx"); //替换
cout<<s1<<endl;
s1.replace(5,3,s2);
cout<<s1<<endl;
string s3("helloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworld");
p = s3.find("world");
while(p != -1) //将字符串中的world 替换为 x;
{
s3.replace(p,strlen("world"),"x");
p = s3.find("world",p+strlen("x"));
}
cout<< s3<<endl;
#endif
//string的插入和删除
string s1("helloworld");
string s2("12345");
s1.insert(0,"this is ");
cout<<s1<<endl;
s1.insert(10,s2);
cout<<s1<<endl;
s1.insert(0,5,'x'); //插入
cout<<s1<<endl;
s1.erase(10,2); //删除
cout<<s1<<endl;
return 0;
}
二、容器
1、概述
容器就是将各种常用的数据结构,如数组、链表、栈、队列、二叉树等封装成一个个模板类,以方便编程。
2、vector
vector是将元素放置在一个动态数组中加以管理的容易,可以随机存取元素,[]或者at直接存取,vector在尾部存取元素十分迅速,但是在中部或者头部插入或者删除 元素比较费时。
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
int main(int argc, char const *argv[])
{
#if 1
int data[10] = {1,2,3,4,5,6,7,8,9,10};
vector<int> v1; //创建数组对象(模板类),无参构造函数
vector<int> v2(data, data + 10); //显示调用,int类型
vector<int> v3(10, 1);
v1.resize(10);
for(int i = 0; i < v1.size(); i++)
{
v1[i] = i;
}
for (int i = 0; i < v1.size(); i++)
{
cout<<v1.at(i)<<" ";
}
cout<<endl;
for (int i = 0; i < v2.size(); i++)
{
cout<<v2.at(i)<<" ";
}
cout<<endl;
for (vector<int>::iterator it = v3.begin(); it != v3.end(); it++) //正向迭代
{
cout<<*it<<" ";
}
cout<<endl;
for (vector<int>::reverse_iterator rit = v2.rbegin(); rit != v2.rend(); rit++)
{
cout<<*rit<<" ";
} //反向迭代
cout<<endl;
for(vector<int>::const_iterator cit = v2.begin(); cit != v2.end(); cit++)
{
//(*cit)++; //只读容器
cout<<*cit<<" ";
}
cout<<endl;
#endif
const char *str = "this is";
const char *s = "helloworld";
vector<char> v(s, s + strlen(s)); //char 类型
for (vector<char>::iterator it = v.begin(); it != v.end(); it++) //迭代
{
cout<<*it;
}
cout<<endl;
v.insert(v.begin(), 'x'); //在前面插入1个 x
for (vector<char>::iterator it = v.begin(); it != v.end(); it++)
{
cout<<*it;
}
cout<<endl;
v.insert(v.begin(), 5, 'x'); //在前面插入5个 x
for (vector<char>::iterator it = v.begin(); it != v.end(); it++)
{
cout<<*it;
}
cout<<endl;
v.erase(v.end() - 5, v.end()); //删除后5个
for (vector<char>::iterator it = v.begin(); it != v.end(); it++)
{
cout<<*it;
}
cout<<endl;
v.erase(v.begin(), v.begin() + 6); //删除前6个
for (vector<char>::iterator it = v.begin(); it != v.end(); it++)
{
cout<<*it;
}
cout<<endl;
v.insert(v.begin(), str, str + strlen(str)); //在前面插入一个 str
for (vector<char>::iterator it = v.begin(); it != v.end(); it++)
{
cout<<*it;
}
cout<<endl;
return 0;
}
3、deque
deque:双端数组,而vector是单端数组,但是两者在接口上非常非常相似,许多操作可以直接替换,deque可以随机存取元素,使用[]或者at() 在deque中,在头部和尾部添加或者删除元素非常迅速,但是在中部添加或者删除则比较费事,头文件:#include <deque>
#include <iostream>
#include <deque>
using namespace std;
int main(int argc, char const *argv[])
{
#if 1
int data[5] = {1,2,3,4,5};
deque<int> d1;
deque<int> d2(data, data + 5); //int 类型
deque<int> d3(10,1);
d1.resize(10);
for (int i = 0; i < d1.size(); i++)
{
d1[i] = i + 1;
}
for (int i = 0; i < d1.size(); i++)
{
cout<<d1[i]<<" ";
}
cout<<endl;
for (deque<int>::iterator it = d2.begin(); it != d2.end(); it++)
{
cout<<*it<<" ";
}
cout<<endl;
d2.push_back(6); //从最后进队 6
d2.push_front(0); //从前面进队 0
for (deque<int>::iterator it = d2.begin(); it != d2.end(); it++)
{
cout<<*it<<" ";
}
cout<<endl;
d2.pop_back(); //从后面出队
d2.pop_front(); //从前面出队
for (deque<int>::iterator it = d2.begin(); it != d2.end(); it++)
{
cout<<*it<<" ";
}
cout<<endl;
d2.front() = 100; //将首元素改为100
d2.back() = 200; //将最后一个元素改为200
for (deque<int>::iterator it = d2.begin(); it != d2.end(); it++)
{
cout<<*it<<" ";
}
cout<<endl;
deque<int>::iterator it = d2.erase(d2.begin()); //删除第一个元素
cout<<*it<<endl;
for (deque<int>::iterator it = d2.begin(); it != d2.end(); it++)
{
cout<<*it<<" ";
}
cout<<endl;
#endif
int data[10] = {2,1,3,3,4,8,7,1,3,3};
deque<int> d(data, data + 10);
for (deque<int>::iterator it = d.begin(); it != d.end();) //删除所有3
{
if (*it == 3)
{
d.erase(it);
}
else
{
it++;
}
}
for (deque<int>::iterator it = d.begin(); it != d.end() ; it++)
{
cout<<*it<<" ";
}
cout<<endl;
return 0;
}
4、list
list:是一个双向链表容器,可高效的进行插入和删除元素,list不支持随机存取元素,所以说不支持[]和at(),也不支持迭代器的随机访问
#include <iostream>
#include <list>
#include <cstring>
using namespace std;
class Student //与链表相同,需要自己定义节点的类型(结构体类型)
{ //在C++中,通常用类,代替结构体类型
private:
int id;
char name[32];
public:
Student(){}
Student(int i, const char *n);
void show();
bool operator==(const Student &s);
};
Student::Student(int i, const char *n)
{
id = i;
strcpy(name, n);
}
void Student::show()
{
cout<<"id = "<<id<<" name = "<<name<<endl;
}
bool Student::operator==(const Student &s)
{
if (s.id == this->id)
{
return true;
}
else
{
return false;
}
}
int main(int argc, char const *argv[])
{
Student s1(1, "aaa");
Student s2(2, "bbb");
Student s3(3, "ccc");
Student s4(4, "ddd");
Student s5(5, "eee");
Student s6(6, "fff");
Student s7(7, "ggg");
list<Student> l; //创建链表对象
l.push_back(s1); //尾插法
l.push_back(s2); //尾插法
l.push_back(s3); //尾插法
l.push_back(s4); //尾插法
l.push_back(s5); //尾插法
l.push_back(s6); //尾插法
for (list<Student>::iterator it = l.begin(); it != l.end(); it++) //迭代
{
it->show();
}
l.pop_back(); //删除最后一个节点
l.pop_front(); //删除第一个节点
cout<<"***********************"<<endl;
//it = it + 1; 不能使用,因为链表是不连续的
for (list<Student>::iterator it = l.begin(); it != l.end(); it++) //迭代
{
it->show();
}
cout<<"最后一个元素是:"<<endl;
l.back().show();
cout<<"第一个元素是:"<<endl;
l.front().show();
cout<<"链表的长度:"<<endl;
cout<<l.size()<<endl;
cout<<"链表的扩充:"<<endl;
l.resize(5,s7);
for (list<Student>::iterator it = l.begin(); it != l.end(); it++) //迭代
{
it->show();
}
//对象数组
cout<<"************************"<<endl;
Student s[5] = {Student{10, "a"},Student{11, "b"},Student{12, "c"},Student{13, "d"},Student{14, "e"}};
l.insert(l.begin(), s[0]);
for (list<Student>::iterator it = l.begin(); it != l.end(); it++) //迭代
{
it->show();
}
cout<<"************************"<<endl;
l.insert(l.end(), 2, s[1]); //在最后插两个s[1]
for (list<Student>::iterator it = l.begin(); it != l.end(); it++) //迭代
{
it->show();
}
cout<<"************************"<<endl;
l.insert(l.end(), s, s + 5); //在最后插入s
for (list<Student>::iterator it = l.begin(); it != l.end(); it++) //迭代
{
it->show();
}
cout<<"删除一个区间"<<endl;
list<Student>::iterator it = l.begin();
for (int i = 0; i < 5; i++)
{
it++;
}
l.erase(it, l.end()); //删除it 后面全部
for (list<Student>::iterator it = l.begin(); it != l.end(); it++) //迭代
{
it->show();
}
cout<<"删除一个位置"<<endl;
l.erase(l.begin()); //删除地一个
for (list<Student>::iterator it = l.begin(); it != l.end(); it++) //迭代
{
it->show();
}
cout<<"删除具体元素"<<endl;
l.remove(s2); //==运算符重载
for (list<Student>::iterator it = l.begin(); it != l.end(); it++) //迭代
{
it->show();
}
cout<<"链表反转"<<endl;
l.reverse();
for (list<Student>::iterator it = l.begin(); it != l.end(); it++) //迭代
{
it->show();
}
return 0;
}
5、stack
//包含头文件 #include <stack>
//栈:同样需要显示调用:如:stack<int> s;
//push() 进栈; top() 栈顶元素; size() 栈的大小; empty() 是否为空; pop() 出栈;
#include <iostream>
#include <stack>
#include <time.h>
#include <cstdlib>
using namespace std;
int main(int argc, const char *argv[])
{
stack<int> s;
srand(sizeof(time(NULL)));
int num;
for (int i = 0; i < 10; i++)
{
num = rand()%10;
s.push(num);
cout<<num<<"进栈成功"<<endl;
}
cout<<"栈顶元素是:"<<s.top()<<endl;
cout<<"栈的大小是:"<<s.size()<<endl;
while (!s.empty())
{
cout<<s.top()<<"出栈"<<endl;
s.pop();
}
return 0;
}
6、queue
//包含头文件 #include <queue>
//push() 进队; front() 队头元素; back() 队尾元素;empty() 是否为空;
#include <iostream>
#include <queue>
using namespace std;
int main(int argc, const char *argv[])
{
queue<int> q;
int num;
for (int i = 0; i < 10; i++)
{
num = i + 1;
q.push(num);
cout<<num<<"进队成功!"<<endl;
}
cout<<"队头元素"<<q.front()<<endl;
cout<<"队尾元素"<<q.back()<<endl;
while(!q.empty())
{
cout<<q.front()<<"出队!"<<endl;
q.pop();
}
return 0;
}
优先队列
//priority_queue 优先队列;如:priority_queue<int> p;
//pop() 出队;push()进队;top()栈顶;empty()栈空
#include <iostream>
#include <queue>
#include <time.h>
#include <cstdlib>
using namespace std;
int main(int argc, char const *argv[])
{
//priority_queue<int> p; //priority_queue<int, vector<int>, less<int>> p; //由大到小排序
//priority_queue<int, vector<int>, greater<int>> p; //由小到大排序,由动态数组构成
priority_queue<int, deque<int>, less<int>> p; //由队列构成
srand(sizeof(time(NULL)));
int num;
for (int i = 0; i < 10; i++)
{
num = rand()%10;
p.push(num);
cout<<num<<"进队成功"<<endl;
}
cout<<"队头元素"<<p.top()<<endl;
cout<<"队的长度"<<p.size()<<endl;
while (!p.empty())
{
cout<<p.top()<<"出队"<<endl;
p.pop();
}
return 0;
}
7、set 容器
//包含头文件 #include <set>
//属于链式存储,故而也需要先定义节点(通过类定义);遍历就是要迭代
//链式存储是有序的,(由小到大 或 由大到小)
// insert() 插入数据; begin() 开始元素; end() 结尾元素; erase() 删除元素或区间;find() 查找(返回 地址);count() 统计相同节点个数;lower_bound() 找到一个比当前元素大一个的元素;
upper_bound() 找到一个比当前元素小一个的元素;
//pair 类的使用:如: pair<参数1,参数2> p; 对象 p 可以通过访问两个参数(p.first;p.second),起到lower_bound();upper_bound()的作用
#include <iostream>
#include <set>
using namespace std;
class Student
{
private:
int id;
string name;
public:
Student(int i, string n);
void show() const;
bool operator<(const Student &s) const;
bool operator>(const Student &s) const;
};
Student::Student(int i, string s)
{
id = i;
name = s;
}
void Student::show() const
{
cout<<"id = "<<id<<" name = "<<name<<endl;
}
bool Student::operator<(const Student &s) const
{
return this->id < s.id;
}
bool Student::operator>(const Student &s) const
{
return this->id > s.id;
}
int main(int argc, const char *argv[])
{
Student s3(3, "cc");
Student s1(1, "aa");
Student s4(4, "dd");
Student s2(2, "bb");
Student s6(6, "ff");
Student s5(5, "ee");
set<Student> s;
//set<Student, greater<Student>> s; //greater<> 由小到大排序
s.insert(s3);
s.insert(s1);
s.insert(s4);
s.insert(s2);
s.insert(s6);
s.insert(s5);
for (set<Student>::iterator it = s.begin(); it != s.end(); it++)
{
it->show();
}
cout<<"集合大小: "<<s.size()<<endl;
s.erase(s.begin());
for (set<Student>::iterator it = s.begin(); it != s.end(); it++)
{
it->show();
}
cout<<"set区间删除"<<endl;
s.erase(--(s.end()), s.end());
for (set<Student>::iterator it = s.begin(); it != s.end(); it++)
{
it->show();
}
cout<<"删除具体的元素"<<endl;
s.erase(s2);
for (set<Student>::iterator it = s.begin(); it != s.end(); it++)
{
it->show();
}
cout<<"set的查找"<<endl;
set<Student>::iterator it = s.find(s4);
if (it == s.end())
{
cout<<"对象不存在"<<endl;
}
else
{
it->show();
}
cout<<"set的统计"<<endl;
cout<<s.count(s4)<<endl;
cout<<"lower_bound"<<endl;
it = s.lower_bound(s4);
if (it == s.end())
{
cout<<"对象不存在"<<endl;
}
else
{
it->show();
}
cout<<"upper_bound"<<endl;
it = s.upper_bound(s3);
if (it == s.end())
{
cout<<"对象不存在"<<endl;
}
else
{
it->show();
}
cout<<"**********************"<<endl;
for (set<Student>::iterator it = s.begin(); it != s.end(); it++)
{
it->show();
}
cout<<"equl_range"<<endl;
//pair 类型 模板类 有两个成员变量:相当于 lower_bound , upper_bound;
pair<set<Student>::iterator, set<Student>::iterator> p;
p = s.equal_range(s4);
p.first->show(); //第一个变量:lower_bound
p.second->show(); //第二个变量:upper_bound
return 0;
}
8、map容器
//map 容器包含两个部分:键(key)、值(value)
//在访问map 对象的内容时,需要指向 键(key)和值(value)两个数据
//begin() 开始元素; end() 结尾元素; erase() 删除元素或区间;
insert() 插入数据;//在接口括号中,调用其它接口
(1)pair<int, string>(1,”zz”) //通过pair对组(组合一组数据)插入
(2)make(1,”aa”) //通过make_pair组合一对数据插入
(3)map<int, string>::value_type(1,”cc”); //通过map内部的静态成员函数插入
(4)m[1] = “aa”; //map重载了[ ]运算符,进行插入
#include <iostream>
#include <map>
using namespace std;
int main(int argc, char const *argv[])
{
map<int,string> m; //key是int型,value是string类型
m.insert(pair<int,string>(3,"aa")); //通过pair对组(组合一组数据)插入
m.insert(pair<int,string>(1,"zz"));
m.insert(make_pair(5,"cc")); //通过make_pair组合一对数据插入
m.insert(make_pair(2,"dd"));
m.insert(map<int,string>::value_type(6,"hh"));
m.insert(map<int,string>::value_type(4,"vv")); //通过map内部的静态成员函数插入
m[8] = "uu"; //map重载了[]运算符
m[7] = "qq";
for(map<int,string>::iterator it = m.begin(); it != m.end();it++)
{
//it指向map的一个结点,一个结点就是一个pair对象,即it指向pair对象,pair对象有两个成员,first和second
cout<<"key: "<<it->first<<" value :"<<it->second<<endl;
}
//前三种插入方式,如果数据已经存在则返回错误,第四种方法,如果数据存在,则覆盖之
pair<map<int,string>::iterator,bool> p = m.insert(make_pair(5,"ll"));
if(p.second == false)
{
cout<<"插入失败"<<endl; //返回迭代器指向已经存在的结点
cout<<"key: "<<p.first->first<<" value :"<<p.first->second<<endl;
}
else
{
cout<<"插入成功"<<endl;
}
m[3] = "www"; //直接将原有数据覆盖
for(map<int,string>::iterator it = m.begin(); it != m.end();it++)
{
cout<<"key: "<<it->first<<" value :"<<it->second<<endl;
}
cout<<"map删除指定位置"<<endl;
m.erase(m.begin());
for(map<int,string>::iterator it = m.begin(); it != m.end();it++)
{
cout<<"key: "<<it->first<<" value :"<<it->second<<endl;
}
cout<<"map删除区间"<<endl;
m.erase(--(m.end()),m.end());
for(map<int,string>::iterator it = m.begin(); it != m.end();it++)
{
cout<<"key: "<<it->first<<" value :"<<it->second<<endl;
}
cout<<"删除具体的元素"<<endl;
m.erase(4); //根据键值来删除
for(map<int,string>::iterator it = m.begin(); it != m.end();it++)
{
cout<<"key: "<<it->first<<" value :"<<it->second<<endl;
}
return 0;
}
9、multimap
一个key值可以对应多个value
案例:
公司: 销售部:2名
技术研发部:1名
财务部:2名
人员信息:姓名,年龄,电话,工资等组成
通过multimap进行信息的插入,保存,显示
分部门显示员工信息
#include <iostream>
#include <map>
using namespace std;
class Employee
{
private:
int id;
string name;
public:
Employee(int i,string n)
{
id = i;
name = n;
}
void show()
{
cout<<"工号:"<<id<<" 姓名:"<<name<<endl;
}
};
int main(int argc, char const *argv[])
{
Employee e1(1,"aa");
Employee e2(2,"bb");
Employee e3(3,"cc");
Employee e4(4,"dd");
Employee e5(5,"ee");
Employee e6(6,"ff");
Employee e7(7,"gg");
Employee e8(8,"hh");
multimap<string,Employee> m; //对象 m 包含了 string、Employee 两个类
//从而达到一个 key 包含多个 信息(value)
//销售部有三个员工
m.insert(make_pair("Sale",e1));
m.insert(make_pair("Sale",e2));
m.insert(make_pair("Sale",e3));
//研发部有一个员工
m.insert(make_pair("development",e4));
//财务部门有四个员工
m.insert(make_pair("Finance",e5));
m.insert(make_pair("Finance",e6));
m.insert(make_pair("Finance",e7));
m.insert(make_pair("Finance",e8));
cout<<m.count("Finance")<<endl;
for(map<string,Employee>::iterator it = m.begin();it != m.end();it++)
{
cout<<"部门:"<<it->first<<endl;
it->second.show();
}
return 0;
}
总结:
三、算法
1、算法
C++中的算法模板主要在三个头文件中:<algotithm>、<numeric>、<functional>;
<algotithm>:包含:遍历算法(可修改值、不可修改值)、查找算法(重复且相邻元素、按值查找、查找出现次数)、排序算法、
(1)遍历算法
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
void show(int x)
{
cout<< x<<endl;
}
class print
{
public:
void operator()(int x)
{
cout<< x<<endl;
}
};
int main(int argc, char const *argv[])
{
int a[5] = {1,2,3,4,5};
vector<int> v(a, a + 5);
//for_each遍历过程中不能修改数据
for_each(v.begin(), v.end(), show); //回调函数形式遍历
for_each(v.begin(), v.end(), print()); //函数对象形式遍历
//tramsform遍历过程中可以修改数据
string s("helloworld");
transform(s.begin(), s.end(), s.begin(), ::toupper); //将小写改为大写
cout<<s<<endl;
return 0;
}
(2)查找算法
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
bool GreaterTwo(int x)
{
return x > 2;
}
class GreaterThree
{
public:
bool operator()(int x)
{
return x > 3;
}
};
int main(int argc, char const *argv[])
{
int a[6] = {1,2,2,3,6,5};
vector<int> v(a, a+6);
//查找重复且相邻的元素
vector<int>::iterator it = adjacent_find(v.begin(), v.end());
if (it == v.end())
{
cout<<"不存在重复且相邻的元素"<<endl;
}
else
{
cout<<*it<<endl;
}
//在有序序列里面找值
bool ret = binary_search(v.begin(),v.end(), 9);
if (ret)
{
cout<<"存在元素"<<endl;
}
else
{
cout<<"不存在元素"<<endl;
}
//查找元素个数
int num = count(v.begin(), v.end(), 2);
cout<<num<<endl;
//查找大于2的个数
num = count_if(v.begin(), v.end(), GreaterTwo);
cout<<num<<endl;
//查找元素
it = find(v.begin(), v.end(), 3);
if (it == v.end())
{
cout<<"不存在元素"<<endl;
}
else
{
cout<<*it<<endl;
}
//查找大于3 的第一个元素
it = find_if(v.begin(), v.end(), GreaterThree()); //函数对象
if (it == v.end())
{
cout<<"不存在元素"<<endl;
}
else
{
cout<<*it<<endl;
}
return 0;
}
(3)排序算法
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void show(int x)
{
cout<< x<<" ";
}
int main(int argc, char const *argv[])
{
vector<int> v1;
vector<int> v2;
srand(sizeof(time(NULL)));
for (int i = 0; i < 5; i++)
{
v1.push_back(rand()%10);
v2.push_back(rand()%10);
}
//将两个数组排序
sort(v1.begin(), v1.end(), less<int>());
sort(v2.begin(), v2.end(), less<int>());
cout<<"v1: "<<endl;
for_each(v1.begin(), v1.end(), show);
cout<<endl;
cout<<"v2: "<<endl;
for_each(v2.begin(), v2.end(), show);
cout<<endl;
//合并两个数组
vector<int> v3;
v3.resize(10);
merge(v1.begin(),v1.end(),v2.begin(),v2.end(),v3.begin());
for_each(v3.begin(), v3.end(), show);
cout<<endl;
//将数组打乱
random_shuffle(v1.begin(),v1.end());
cout<<"v1: "<<endl;
for_each(v1.begin(), v1.end(), show);
cout<<endl;
//转直
reverse(v3.begin(),v3.end());
for_each(v3.begin(), v3.end(), show);
cout<<endl;
return 0;
}
(4)拷贝替换
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void show(int x)
{
cout<<x<<" ";
}
int main(int argc, char const *argv[])
{
vector<int> v1(5,1);
vector<int> v2(5,2);
//将v2覆盖
v2.resize(6);
copy(v1.begin(),v1.end(),++(v2.begin()));
for_each(v2.begin(),v2.end(),show);
cout<<endl;
//将v1和v2互换
swap(v1,v2);
for_each(v2.begin(),v2.end(),show);
cout<<endl;
return 0;
}
2、函数对象
(1)概念
重载函数调用操作符的类,其对象称为函数对象,即他们的行为类似函数,一个类的对象,表现出一个函数的特征,就是通过 “对象名 +(参数列表)”的方式 使用一个类对象,如果没有上下文,完全可以当成一个函数队列
函数对象:主要通过重载()来实现的
(2)谓词
一元函数对象:函数参数1个;二元函数对象:函数参数2个
一元谓词函数:参数1个,函数返回值是bool类型,可以作为一个判断式
谓词可以是一个仿函数,也可以是一个回调函数
二元谓词:函数参数2个,函数返回值是bool类型
一元谓词函数举例:
判断string对象的长度是否小于6
bool Greater(Const string &s)
3、函数适配器
四大类:绑定适配器,组合适配器,指针函数适配器,成员函数适配器
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
bool Equal(string str)
{
return str == "bb";
}
int main(int argc, char const *argv[])
{
vector<string> v;
v.push_back("aa");
v.push_back("bb");
v.push_back("cc");
v.push_back("dd");
v.push_back("ee");
//查找相同字符串
//vector<string>::iterator it = find_if(v.begin(),v.end(),Equal); //调用函数
vector<string>::iterator it = find_if(v.begin(),v.end(),bind1st(equal_to<string>(),"bb")); //运用适配器
if (it == v.end())
{
cout<<"不存在"<<endl;
}
else
{
cout<<*it<<endl;
}
return 0;
}