C++学习:STL-函数对象、算法

函数对象:
函数对象是可以以函数方式与()结合使用的任意对象,包括:
1)函数名; 
2)指向函数的指针; 
3)重载了()操作符的类对象(即定义了函数operator()的类)。 

算法:  
算法是对迭代器进行操作的,不是对特定的容器。

STL将算法库分为4组, 前3个在algorithm头文件中描述,而第4个在numeric头文件中描述。
1) 非修改式序列操作:不改变容器的内容,如find()、for_each()等。 
2) 修改式序列操作:可以修改容器中的内容,如transform()、random_shuffle()、copy等。 
3) 排序和相关操作:包括各种排序函数等,如sort()等。 
4) 通用数字运算:计算两个容器的内部乘积等。 

一、不可修改序列内容的算法:


for_each函数的使用 
将一个函数应用于某一范围的元素。
例:
#include <iostream>
#include <vector>
#include <algorithm>
using std::cout;
using std::endl;
using std::vector;

void print(vector<int>::value_type & v){                     //print函数。将元素自增2后输出。vector<int>::value_type多余,可以直接写int。传的                                                                                 是引用,可以改变值。如果不写引用,则改不了。 
        v += 2;
        cout << v << " ";
}

int main(){
        vector<int> vecInt = {1, 2, 3, 4, 5, 6};
        for_each(vecInt.begin(), vecInt.end(), print);        //将函数print应用于vecInt.begin()到vecInt.end()之间的元素。
        cout << endl;

        for(auto & elem : vecInt)                                    //3 4 5 6 7 8 。说明传递的是引用,真的修改了。
                cout << elem << " ";
        cout << endl;

        return 0;
}

二、可以修改序列内容的操作  


replace_if的使用  
将满足特定条件的元素替换为另一个值。
例1:
#include <iostream>
#include <algorithm>
#include <vector>
using std::cout;
using std::endl;
using std::vector;

int main(void){
        vector<int> vecInt = {1, 2, 3, 4, 5, 6};

        std::less<int> lt;                                                                 //二元断言。断言理解为返回bool型的一个函数。二元就是需要两个参数
        replace_if(vecInt.begin(), vecInt.end(), bind1st(lt,3), 7);       //bind1st是一个函数适配器。将3与lt的第一个参数进行绑定。lt需要两个参                                                                                                数,当第一个参数小于第二个参数时,返回true。所以当3小于元素时,返                                                                                                回true;当3大于元素时,返回false.当返回true时满足条件,会将元素替换为7 
        for(auto & elem : vecInt)                                                   //输出1 2 3 7 7 7 
                cout << elem << " ";  
        return 0;
}


remove_if的使用  
例1:迭代器失效的情况
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using std::cout;
using std::endl;
using std::vector;
using std::string;

int main(void){
        vector<string> vecStr;
        vecStr.push_back("hello");
        int i = 0;

        auto it = vecStr.begin();                                          //auto关键字。该句相当于:vector<string>::iterator it; it = vec.begin();  it指向一块存                                                                                     储区的位置。 
        for(; it != vecStr.end(); ++it){                                
                cout << vecStr.capacity() << endl;                   //第一次进来时,capacity为1 
                cout << *it << endl;
                if(0 == i){
                        vecStr.push_back("world");                     //容器插入元素"world".此时底层做了扩容的操作, 另开辟了一块空间,存放元素。                                                                                        而迭代器it还是指向了原来的空间。当执行++it时,出错。
                        cout << "vecStr.push !" << endl;
                        i = 1;
                }
        }
}

例2:erase-remove惯用法
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using std::cout;
using std::endl;
using std::vector;
using std::string;

int main(void){
        vector<int> vecInt;
        vecInt.reserve(10);
        cout << vecInt.size() << endl;                                     //0
        cout << vecInt.capacity() << endl;                              //10

        for(int idx = 1; idx <= 10; ++idx){
                vecInt.push_back(idx);
        }

        vecInt[3] = vecInt[5] = vecInt[9] = 99;

        for(auto & elem : vecInt)
                cout << elem << " ";                                         //1 2 3 99 5 99 7 8 9 99
        cout << endl;


        vecInt.erase(std::remove(vecInt.begin(), vecInt.end(), 99),vecInt.end());   //remove(vecInt.begin(),vecInt.end,99)之后指针指向的位置之后                                                                                                                   的元素就不要了。需要erase。这样的用法叫做:erase-remove                                                                                                                     惯用法。remove不直接删掉就是因为害怕出现迭代器失效的问                                                                                                                   题。所以remove不直接删除数据,而是尽量往后移动,移完之                                                                                                                   后再统一删除。
        cout << "删除99之后:" << endl;
        for(auto & elem : vecInt)
                cout << elem << " ";
        cout << endl;

}

三、分块操作、排序操作、二叉排序操作 


四、集合操作、堆操作  



五、最小最大操作、数字操作、C库 

















猜你喜欢

转载自blog.csdn.net/pengchengliu/article/details/80545241