目录
一、算法
(1)简介
算法由头文件<algorithm>,<numeric>,<functional>组成
- <algorithm> 是头文件中最大的,包含的功能有比较、交换、查找、遍历、复制、修改、反转、排序、合并等
- <numeric> 只包括在序列上进行简单数学运算的模板函数,包括加法和乘法在序列上的一些操作
- <functional> 定义了一些模板类,用来声明函数对象
(2)STL常见算法
-
非可变序列算法
不直接修改所操作容器内容的算法
find() 查找容器元素
find_if() 条件查找容器元素
#include <algorithm>
//for_each函数的头文件
//find()
vector<int> v1;
for(int i=0;i<10;i++)
{
v1.push_back(2*i);
}
for_each(v1.begin(),v1.end(),MyPrint); //MyPrint为之前定义的函数
vector<int>::iterator it1 = find(v1.begin(),v1.end(),5); //查找成功返回迭代器,失败返回v1.end()
//find_if()
bool DivBy5(int x)
{
return x%5? 0:1;
}
vector<int>::iterator it2 = find_if(v1.begin(),v1.end(),DivBy5); //返回第一个能被5整除的元素
count() 统计元素的个数
count_if() 条件统计元素的个数
//count()
int num1 = count(v1.begin(),v1.end(),3);
//count_if()
int num2 = count(v1.begin(),v1.end(),DivBy5); //第3个参数是条件函数
search() 子序列搜索,返回子序列在父序列中起始位置
search_n() 重复元素的子序列搜索
//search()
vector<int> v2; //子序列
for(int i=0;i<2;i++)
{
v2.push_back(i+8);
}
vector<int>::iterator it3 = search(v1.begin(),v1.end(),v2.begin(),v2.end());
//前2个参数是搜索序列的范围,后2个参数是子序列范围
//search_n()
vector<int>::iterator it4 = search(v1.begin(),v1.end(),3,8);
//在v1中搜索子序列 8 8 8
-
可变序列算法
修改所操作容器内容的算法
copy() 元素复制
transform() 元素变换,也是复制,按照某种方案复制
//copy()
vector<int> v;
v.push_back(1);
v.push_back(3);
v.push_back(5);
list<int> l;
l.push_back(2);
l.push_back(4);
l.push_back(6);
l.push_back(8);
copy(v.begin(),v.end(),l.begin()); //把v拷贝到l的头部,会覆盖l的数据
//transform(),按照规则拷贝
int square(int x)
{
return x*x;
}
transform(v.begin(),v.end(),l.begin(),square); //把v的平方拷贝到l的头部,会覆盖l的数据
replace() 替换元素
replace_if() 条件替换
//replace()
replace(v.begin(),v.end(),5,100); //将所有5替换成100
//replace_if()
bool odd(int x)
{
return x%2;
}
replace_if(v.begin(),v.end(),odd,100); //将奇数替换成100
remove() 删除元素
remove_if() 条件删除
//remove()
remove(v.begin(),v.end(),5); //删除值为5的元素,但数组大小不变
//删除前 1 3 5 7
//删除后 1 3 7 7
//remove_if()
bool even(int x)
{
return x%2?0:1;
}
remove_if(v.begin(),v.end(),even) //删除奇数
//删除前 1 2 3 4 5 6 7 8 9 10
//删除后 1 3 5 7 9 6 7 8 9 10
-
排序算法
sort() 普通排序
make_heap() 将一个区间转换成堆
sort_heap() 对堆进行排序,排序后就不是堆了
//sort()
sort(v.begin(),v.end()); //参数为要排序的区间,默认升序排列
//make_heap()
make_heap(v.begin(),v.end()); //将区间转换成大根堆
//sort_heap()
sort_heap(v.begin(),v.end()); //对堆进行排序,默认升序排列
二、迭代器
(1)简介
迭代器用于指向容器中的一个元素,有const和非const两种
通过迭代器可以读取它指向的元素,通过非const迭代器可以修改它指向的元素
不同容器支持的迭代器功能强弱不同,迭代器功能强弱决定了该容器是否支持STL中的某种算法
定义迭代器:
容器类名:: iterator 变量名 ,如 vector<int>::iterator v;
容器类名:: const_iterator 变量名 ,如 vector<int>::const_iterator v;
访问迭代器指向的元素:
* 迭代器变量名
迭代器功能由弱到强分为5种
1.输入:Input iterators 提供对数据的只读访问
1.输出:Output iterators 提供对数据的写访问
2.正向:Forward iterators 提供读写操作,并能向前推进迭代器
3.双向:Bidirectional iterators 提供读写操作,并能向前和向后操作
4.随机:Random access iterators 提供读写操作,并能在数据种随机移动(能使用[ ]操作符)
编号大的迭代器拥有编号小的迭代器的功能,能当编号小的迭代器使用
不同迭代器能进行的操作
所有迭代器: ++p,p++
输入迭代器:*p,p=p1,p==p1,p!=p1
输出迭代器:*p,p=p1
正向迭代器:上面全部
双向迭代器:上面全部,--p,p--
随机访问迭代器:上面全部,
p+=i,p-=i, p+i,p-i,p[i],
p<p1,p<=p1,p>p1,p>=p1 (迭代器比较操作)
容器 | 迭代器类别 |
vector | 随机 |
deque | 随机 |
list | 双向 |
set / multiset | 双向 |
map / multimap | 双向 |
stack | 不支持 |
queue | 不支持 |
priority_queue | 不支持 |
(2)迭代器操作
//p<p1,p<=p1,p>p1,p>=p1
int arr[] = {11,12,13,14,15,16,17,18,19,20};
vector<int> v(arr,arr+9);
vector<int>::const_iterator it1 = v.begin(); //常量迭代器,指向第一个元素11
vector<int>::const_iterator it2 = v.cbegin(); //常量迭代器,指向第一个元素11
//cbegin()和cend()方法,返回一个const的迭代器,不能用于修改元素
vector<int>::iterator it3 = v.begin();
*it3 = 10; //修改第一个元素值为10
it3++; //指向第二个元素
//迭代器的比较是按照迭代器指向的值来进行比较
(3)STL使用自定义对象
向vector,deque,list,stack,queue添加自定义对象,实际是将对象复制到容器中,要调用对象的拷贝函数;
如果定义了拷贝函数就调用定义的拷贝函数,否则就调用默认的拷贝函数;
向set和map容器添加自定义对象也是将对象复制到容器中,不同的是set和map容器要实现比较器函数;
- vector容器
class member
{
private:
string m_str;
int m_id;
public:
member(const string str,const int id):m_str(str),m_id(id){}; //构造函数
void MyPrint()
{
cout<< m_str << ":" << m_id;
}
};
vector<member> v1;
v1.push_back(member("123",1));
v1.push_back(member("456",2));
vector<member> v2(v1); //用v1初始化v2
vector<member>::iterator it = v2.begin();
it-> MyPrint(); //打印结果为123:1
- set容器
class student
{
private:
int s_str; string s_id;
public:
student(const int id,const string str)
{
s_id= id; s_str = str;
}
void MyPrint()const //const成员函数
{
cout<< s_str << ":" << s_id;
}
};
//小于比较器
struct stuFun
{
bool operator()(const student& stu1,const student& stu2)
{
return(stu1.s_id < stu2.s_id)
}
};
set<student,stuFun> s1;
s1.insert(student(7,"小A"));
s1.insert(student(5,"小B"));
s1.insert(student(3,"小C"));
s1.insert(student(1,"小D")); //按id进行升序排列
set<student,stuFun> s2(s1);
set<student,stuFun>::iterator it = s2.begin();
it-> MyPrint(); //打印结果为 小D:1
三、类中成员函数声明后面接 const
- const 表示对类中成员函数属性的声明;
- 表示不会修改类中的数据成员;
- 在编写const成员函数时,若不慎修改了数据成员,或者调用了非const成员函数,编译器报错;
class S
{
private:
int num;
int data[100];
public:
void Push(int elem);
int Pop(void);
int GetCount(void) const; //const成员函数
};
//注意:在实现的时候需要带有const修饰
int S::GetCount(void)const
{
++num; //编译错误,企图修改数据成员num
Pop(); //编译错误,企图调用非const函数
return num;
}
类中被const声明的成员函数只能访问const成员函数,而非const函数可以访问任意的成员函数,包括const成员函数
类中被const声明的成员函数不可以修改对象的数据,不管对象是否具有const性质,它在编译时,会检查是否修改成员数据
加上mutable修饰符的数据成员,对于任何情况下通过任何手段都可修改,自然此时的const成员函数是可以修改它的