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);