标准库一些常用的东西

版权声明: https://blog.csdn.net/dashoumeixi/article/details/86268843

1.以下的一些东西无法用以关联容器,set/map ..
  这些根据二叉树的容器在插入时已根据 const key 排序了,因此通用排序的算法已无法再次修改;

2.下面代码中使用了很多函数对象(like function) / 可调用的对象 :
  无非是 函数指针, 重载operator()( args )  函数的class/struct ,  std::bind , lambda 这四类罢了. 下面代码中lambda用的比较多一些就是图方便

3. 有些命名的规则
   xxx_if : _if 结尾的基本会要求传一个函数对象
   xxx_copy : 带copy的函数, 一般不会对原对象操作, 而是操作后复制到目标迭代器中.例如
   remove_copy(x.begin(),x.end(), 目标范围 ,某个值); 只会把某个值移除后再复制到目标;

 带stable的 (例如: stable_partition   ), 在重新排序后原本相对次序依旧能保持


下面代码中有个打印函数:
template <typename Iter>
void print(Iter  b, Iter e, const std::string& str = "print:")
{
    cout << str ;
    while(b != e)
        cout << *b++ << ' ';
    cout << endl;
}
template<typename T>
void print(const T & c, const std::string & str="print:")
{
    typename T::const_iterator pos;
    cout << str;
    for( pos = c.begin() ; pos != c.end() ; ++pos)
        cout << *pos << ' ';
    cout << endl;
}
for_each / transform : 都可以直接改动原容器,只是 transform  更强大
    vector<int> vi{1,4,4,5,6,1,2,2,3,1,6,6,6};

    //lambda 可以换成 void add10(int &d){ d+= 10;}
    for_each(vi.begin(),vi.end(),[&](int& d){return d+=10;})  ;
    print(vi);
    transform(vi.begin(),vi.end(),vi.begin(),[&](int &d){ return d+=11;});
    print(vi);
count / count_if : 计数
下面使用了 bind .简单说明下:
using std::placeholders::_1; //占位符, _1, _2,_3 ....

//有这么个函数;
void func(int x, int y){ ... }


// _1 相当于 x, y 现在已经被确定是10
auto call = std::bind(func,_1, 10)    将返回一个可调用对象

由于y已经被确定是10了; 所以可以这么调用

call(100) 相当于 -> func(100,10)
    using std::placeholders::_1;   // bind 需要用 . count_if需要一个参数的函数

    vector<int> vi{1,4,4,5,6,1,2,2,3,1,6,6,6};

      
    cout << "find 6 : "<< count(vi.begin(),vi.end(),6) << endl;


    //找小于 5 的. std::less<int>() 是一个函数对象, 用std::bind 确定第2个参数
    //std:bind 将返回一个可调用对象(function object) . 并接受一个参数 ;
    cout << "less than 5:" << count_if(vi.begin(),vi.end(),
                              std::bind(std::less<int>(),_1,5)
                              ) << endl;


    cout <<"not odd:" << count_if(vi.begin(),vi.end(),[&](const int & d){ return d % 2 != 0;}) << endl;

partition/stable_partition : 重排容器. 例如把置顶的排到前面;
//把偶数排到前面:
    vector<int> vi{1,4,4,5,6,1,2,2,3,1,6,6,6};
    vector<int> vi1{1,4,4,5,6,1,2,2,3,1,6,6,6};

    //std::bind(std::modulus<int>(),_1,2)  也可替换lambda
    auto pos = stable_partition(vi.begin(),vi.end(),[&](const int& v){
        return v % 2 == 0;
    });
    cout << "pos:" << *pos << ", dis:" << distance(pos,vi.begin()) << endl;
    print(vi);
    //std::bind(std::modulus<int>(),_1,2)
    pos = partition(vi1.begin(),vi1.end(),[&](const int& v){ return v %2==0;});
    print(vi1);

find/find_if : 找到一个元素

 list<int> li {1,2,3,4,4,6,5,7};

    //找5
    auto pos = find(li.begin(),li.end(),5);
    if(pos != li.end())
        cout << "值:" << *pos << ",距离多远:" <<  distance(li.begin(),pos) << endl;

    //找第一个  >3 的. bind可完全由lambda表示
    pos = find_if(li.begin(),li.end(),std::bind(greater<int>(),_1,3));
    if(pos != li.end())
        cout << "第一个大于3的:" << *pos << endl;

    //找第一个被2能整除的
    pos = find_if(li.begin(),li.end(),[&](const int& d){
        return d % 2 ==0;
    });
    if(pos != li.end())
        cout << "odd:" << *pos << endl;

equal: 用于比较2个容器内的元素是否一致. 下面有带函数的版本:

//元素长度得一致.
list<int> li {1,2,3,4,4,6,5,7};
vector<int> vi{2,3,3,4,4,6,5,7};


  //用于比较是否 vector中的所有元素都>= list中的
  cout << equal(li.begin(),li.end(),vi.begin(),[&](const int&a,const int&b) -> bool{
        return b >= a;
    }) << endl;

copy :  copy没有copy_if . 但有remove_copy_if / replace_copy_if:

 
list<int> li ;
vector<int> vi{2,3,3,4,4,6,5,7};

    //back_insert 将调用 li.insert 
    copy(vi.begin(),vi.end(),back_inserter(li));
    print(li);

    //清空
    li.clear();
    copy(vi.rbegin(),vi.rend(),back_inserter(li));
    print(li);

    li.clear();

    //只把vector 中 >=4 的copy到list中
    remove_copy_if(vi.begin(),vi.end(),back_inserter(li),std::bind(std::less<int>(),_1,4));
    print(li);
transform : 牛逼的复制 与自我赋值;
     vector<int> vi{2,3,3,4,4,6,5,7};
    
    //自增操作
    transform(vi.begin(),vi.end(),vi.begin(),[&](const int & d){
        return  d+10;
    });
    print(vi);

 //把vector正序与反序相加到 list 中
    transform(vi.begin(),vi.end(),vi.rbegin(),back_inserter(li),std::plus<int>());
    print(li);

replace/replace_if / replace_copy_if: 替换. 注意带copy的一般不会对原容器改变

    vector<int> vi{2,3,3,4,4,6,5,7};

    //直接把5替换成10;
    replace(vi.begin(),vi.end(),5,10);
    print(vi);

    //把小于4的替换成10
    replace_if(vi.begin(),vi.end(),
                    std::bind(std::less<int>(), _1, 4) ,//lambda: [](const int&d){ return d < 4;}
                   10); //新值10;
    print(vi);


    // 原vector并不改变, 仅仅把原容器中的10全替换成1 并输出到 cout
    replace_copy(vi.begin(),vi.end(),ostream_iterator<int>(cout," "),10,1);
    cout << endl;


    //原vector 不改变.  把vector中的10 全替换成100,输出到list中
    replace_copy_if(vi.begin(),vi.end(),back_inserter(li),[&](const int &d){
        return d == 10;
    },100);
    print(li);
    

remove / remove_if / remove_copy_if:  移除 . remove这个函数并不会直接把元素直接移除,然后万事大吉.而是找到需要移除的

元素,然后把目标元素移除后, 把目标元素后面的元素依次往前移动. 所以要在原容器中移除需要再次调用erase;

 vector<int> vi{2,3,3,4,4,6,5,7};

    // remove 返回一个迭代器. 指向要删除的第一个元素
    auto pos = remove(vi.begin(),vi.end(),5);
    cout << "pos:" << *pos <<  ", distance:" << distance(vi.begin(),pos) << endl;
    print(vi , "before remove:");  //可以看到5移除了. 5后面的元素复制到了前面
    vi.erase(pos,vi.end());     //真正的移除
    print(vi,"after remove:");

    //remove_if : 同样的. 返回指向删除的第一个元素的迭代器
    pos = remove_if(vi.begin(),vi.end(),std::bind(std::less<int>() , _1, 6));
    cout << "pos:" << *pos << endl;
    print(vi, "before remove:");   //出乎意料吗?
    vi.erase(pos,vi.end());         //真的移除了
    print(vi , "after remove:");


    //remove_copy : 带copy 不以改变原容器 .
    remove_copy(vi.begin(),vi.end(),ostream_iterator<int>(cout," ") , 6);
    cout << endl;

     //>6的复制到输出流
    remove_copy_if(vi.begin(),vi.end(),ostream_iterator<int>(cout," ") ,
                   [&](const int & d){ return d > 6;});
rotate : 让某个区间成为第一个元素;
vector<int> vi{2,3,3,4,4,6,5,7};

    //让 begin() + 1 到 end() 成为一个元素
    rotate(vi.begin(),vi.begin()+1,vi.end());
    print(vi);
    
    //把最后2个元素称为新的首元素
    rotate(vi.begin(),vi.end()-2 , vi.end());
    print(vi);

猜你喜欢

转载自blog.csdn.net/dashoumeixi/article/details/86268843
今日推荐