文章目录
- 算法
- 迭代器
- 容器适配器
- 栈(stack)
- 队列(queue)
- 仿函数
算法
STL中的算法头文件位于和文件中(以为主)
- for_each(InputIterator First,InputIterator Last,Function _Func); 遍历,具体做什么事取决于第三个方法参数。
void show(int a) {
cout << a << " ";
}
void show1(int &a) {
if (a % 2 == 1) {
a += 1;
}
}
vector<int> vec{ 1,2,3,4 };
//遍历
::for_each(vec.begin(), vec.end(), &show); cout << endl;
//如果是奇数就+1
::for_each(vec.begin(), vec.end(), &show1);
::for_each(vec.begin(), vec.end(), &show); cout << endl;
- count(InputIterator First,InputIterator Last,const Type& Val),统计指定范围内的元素的数量。
list<int> lst{ 5,1,1,6,1,0,1 };
cout << ::count(lst.begin(), lst.end(), 1) << endl; //4
cout << ::count(lst.begin(), --lst.end(), 1) << endl; //3
- bool equal(InoutIterator First1,InputIterator Last1,InputIterator First2),比较First1Last1范围内的元素的值,与起始的First2诸葛比较是否相等。相等返回true,否则返回false。First容器元素数不能小于First1Last1。
list<char> lst2{ 1,2,3,4 };
list<char> lst3{ 1,2,3,4,5 };
cout << ::equal(lst2.begin(), lst2.end(), lst3.begin()) << endl; //1
list<char> lst4{ 0,1,2,3,4,5 };
cout << ::equal(lst2.begin(), lst2.end(), ++lst4.begin()) << endl; //1
- InputIterator find(InputIterator First,InputIterator Last,const Type& Val)。范围查找元素,如果找不到返回Last
vector<int>::iterator ite = ::find(vec.begin(), vec.end(), 6);
if (ite != vec.end()) {
cout << *ite << endl;
}
else {
cout << "没找到" << endl;
}
- void sort(RandomAccessIterator first,RandomAccessIterator last,Predicate comp);不能对链表进行排序,链表自带了sort功能函数,map、set会自动排序。
vector<int> vec3{ 5,1,3,0 };
::sort(vec3.begin(), vec3.end(), greater<>()); //降序
::for_each(vec3.begin(), vec3.end(), &show);
cout << endl;
::sort(vec3.begin(), vec3.begin()+2, less<>()); //升序
::for_each(vec3.begin(), vec3.end(), &show);
cout << endl;
- const Type& max(const Type&Left,const Type& Right);返回相比最大的容器,是复制一份。
vector<int> vec4{ 3,6 };
vector<int> v1 = ::max(vec4, vec3);
::for_each(v1.begin(), v1.end(), &show); //3 6
- const Type& min(const Type&Left,const Type& Right);返回相比最小的容器,是复制一份。
void show2(pair<string,int> pr) {
cout << pr.first << "-" << pr.second << endl;
}
map<string, int> m1{ {"12",10} };
map<string, int> m2{ {"12",11} };
map<string, int> m = ::min(m1, m2);
::for_each(m.begin(), m.end(), &show2); cout << endl;
键值优先比较,简直相同比较实值
map<string, int> m3{ {"11",11} };
map<string, int> mm = ::min(m1, m3);
::for_each(mm.begin(), mm.end(), &show2); cout << endl;
迭代器
算法-迭代器-容器之间的关系:
用正常迭代器遍历链表:
list<int> lst{ 1,2,3,4 };
list<int>::iterator ite = lst.begin();
while (ite != lst.end()) {
cout << *ite << " ";
ite++;
}
cout << endl;
那现在我们想要反着去遍历我们该怎么办呢?
正常的思路就是我们让迭代器指向尾,然后如果不等于头就减减
ite = lst.end();
while (ite != lst.begin()) {
cout << *--ite << " ";
//ite--;
}
cout << endl;
注意:因为尾节点没有实际意义,所以不能先取值再减减,可以在取值的同时加上一个左减减,这样每次输出的就是迭代器指向的前一个节点的值,同时也避免了取不到头节点的现象。
那么以上的例子不是真正意义上的反向迭代器,下面我们就来看真正的反向迭代器。
反向迭代器:reverse_iterator,rbegin(),反向的头,rend(),反向的尾。
reverse_iterator::base(),反向迭代器转正向迭代器。
list<int>::reverse_iterator revIte = lst.rbegin(); //定义一个反向迭代器指向反向的头
while (revIte != lst.rend()) {
cout << *revIte << " ";
revIte++;
}cout << endl;
在删除节点时,函数中只能传入正向迭代器,所以要将反向迭代器转为正向迭代器,并且转正后会向后偏移一位,所以要对迭代器进行左减减操作,然后用正常迭代器接一下。
revIte = lst.rbegin();
while (revIte != lst.rend()) {
if (*revIte == 2) { //匹配后,删除节点
ite = --revIte.base(); //反向迭代器转为正向迭代器,转正后会向后偏移一位
cout << "转正后:" << *ite << endl;
lst.erase(ite);
break;
}
revIte++;
}cout << endl;
容器适配器
容器适配器即是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素。容器适配器本质上还是容器,只不过此容器模板类的实现,利用了大量其他基础容器模板类中已经写好的成员函数。当然也可以添加新的成员,他是一个封装了序列行容器的模板类,他在一般序列容器的基础上提供了一些不同的功能。之所以称为适配器类,是因为它可以通过适配器现有的接口来提供不同的功能,将不适用的序列式容器(包括vector、deque和list)变得适用。容器适配器不支持迭代器、当然也就不能使用算法(algorithm)函数。
注意:容器适配器默认都是用底层序列性容器实现的。
容器适配器主要包括:stack栈适配器、queue队列适配器。
栈(stack)
实现的是一个后入先出(Last-In-First-Out,LIFO)的压入栈。它默认是用deque<_Ty>去实现的,但也可以用list vector等底层容器实现。
stack<int> st;
st.push(1);
st.push(2);
st.push(3);
st.push(4);
cout << "size = " << st.size() << endl;
while (!st.empty()) {
cout << st.top() << " "; //查看栈顶元素的值
st.pop(); //栈顶出战
}
cout << endl;
cout << "size = " << st.size() << endl;
队列(queue)
特点:实现的是一个先入先出(First-In-First-Out,FIFO)的队列,它默认是用deque<_Ty>去实现的,但也可以用list等底层容器实现。
queue<int> que;
que.push(1);
que.push(2);
que.push(3);
que.push(4);
cout << "front = " << que.front() << " back = " << que.back() << endl;
cout << "size = " << que.size() << endl;
while (!que.empty()) {
cout << que.front() << " ";
que.pop();
}
cout << endl;
cout << "size = " << que.size() << endl;
仿函数
仿函数的通俗定义:仿函数(functor)又称为函数对象(function object)是一个能行使函数功能的类。仿函数的语法几乎和我们普通函数调用一样,不过作为仿函数的类,都必须重载operator()运算符。
先来写一个真函数:
int add(int a, int b) {
return a + b;
}
cout << add(10, 20) << endl;
仿函数:
class CAdd { //仿函数: 有状态的函数
public:
int sum;
CAdd():sum(0){}
int operator() (int a, int b) {
sum += a + b;
return a + b;
}
};
CAdd Add;
cout << Add(10, 30) << endl;
cout << Add(40, 50) << endl;
cout << "sum = " << Add.sum << endl;
仿函数的优势:它是有状态的函数,他也有类的特性,除了可以增加成员函数外还可以增加成员属性,就像上面的我们增加一个sum用来记录每次加的结果后累加。