STL算法
在前面对于算法已经简要的说明了一下。后面几个部分我会对于算法的详细内容进行更一步的介绍。这篇博客主要记录算法中的主要类别之一的修改类(可能这种区分不严谨,不要太钻牛角尖)。
修改类算法
修改类算法主要的特征是算法中涉及的元素的值可能会发生改变(可能是元素本身也有可能是元素的一个副本)。最为常见的修改类算法是for_each( )和transform( )。两者的主要区别是前面一个在算法中直接对元素进行操作,采用的方法是引用。后者则是对元素的副本进行操作,完成操作后在将值返回以此来完成修改。相比较而言,前者在效率方面更有优势,因为它不需要赋值和拷贝操作。主要修改类算法与代码实例:
操作 | 说明 |
---|---|
for_each(beg,end,op) | 对范围内每个元素进行op操作(也可能元素不发生变化,例如遍历) |
copy(beg,end,destbeg) | 将源范围内的元素拷贝到destbeg开头的范围 |
copy_if(beg,end,destbeg,op) | 将范围内符合准则op的拷贝destbeg开头的范围。c++11 |
copy_n(beg,num,destbeg) | 就beg开始的num个元素拷贝到开头的范围内。c++11 |
copy_backward(beg,end,destend) | 拷贝先从源范围的end开始拷贝到destbend依次往前,需要支持反向迭代。 |
move(beg,end,destbeg) | 将源范围内的元素移动到destbeg c++11 |
move_backward(beg,end,destend) | 从end开始进行移动到destend操作,依次反向迭代进行。c++11 |
fill(beg,end,value) | 将[beg,end)内范围的值重置为value |
fill_n(beg,n,value) | 将beg开始的n个元素的值重置为value |
generate(beg,end,g) | 将[beg,end)范围内的元素重置为g生产的值 |
generate_n(beg,n,g) | 就beg开始范围内的n个元素重置为g生产的值 |
transform(beg,end,destbeg,unaryop) | 范围[beg,end)进行unaryop并保存结果 |
transform(beg1,end1,beg2,destbeg,binaop) | 范围[beg1,end1)与beg2开始范围进行binaop并保存结果 |
remove(beg,end,value) | 将[beg,end)内值为value的元素 |
remove_if(beg,end,op) | 将[beg,end)内op操作返回为真的元素 |
remove_copy(beg,end,destbeg,value) | 将[beg,end)范围内元素值为value的元素拷贝到destbeg |
remove_copy_if(beg,end,destbeg,op) | 将[beg,end)范围内元素值op操作返回为真的拷贝到destbeg |
replace(beg,end,old_value,new_value) | 将[beg,end)范围内元素值为old_value的变换为new_value |
replace_if(beg,end,op,new_value) | 将[beg,end)范围内元素值op操作为真的值变换为new_value |
replace_copy(beg,end,destbeg,old,new | 将[beg,end)范围内元素值为old的变换为new并拷贝到destbeg |
replace_copy_if(beg,end,destbeg,op,new) | 将[beg,end)范围内op操作为真的值变换为new并拷贝到destbeg |
swap_ranges(beg1,end,beg2) | 将[beg1,end2)内的元素与beg2开头的元素进行交换 |
iter_swap(it1,it2) | 将迭代器it1,it2所指元素的值进行交换 |
reverse(beg,end) | 将[beg,end)范围内的元素进行反转(迭代器必须支持反向迭代) |
reverse_copy(beg,end,destbeg) | 将[beg,end)反转拷贝到destbeg |
rotate(beg,beg+n,end) | 将范围[beg,end)循环左移n |
rotate_copy(beg,beg+n,end,destbeg) | 将范围[beg,end)循环左移n,并将移动后的元素拷贝到destbeg |
random_shuffle(beg,end) | 将[beg,end)范围内的的元素置为乱序 |
random_shuffle(beg,end,g) | 将[beg,end)范围内的的元素使用g置为乱序 |
shuffle(beg,end,g) | 将[beg,end)范围内的的元素使用g置为乱序 |
unique(beg,end) | 将[beg,end)内相邻的形同值元素删除 |
unique_copy(beg,end,destbeg) | 将[beg,end)内相邻的形同值元素删除后元素全部复制到destbeg |
几个算法的实例
#include <iostream>
#include <algorithm>
#include <vector>
int main()
{
std::vector<int> v{1, 2, 2, 2, 3, 3, 2, 2, 1};
std::vector<int>::iterator last;
last=std::unique(v.begin(), v.end());
std::vector<int>::iterator it
for (it = v.begin(); it != last; ++it) {
std::cout << *it << " ";
}
std::cout << "\n";
}
//输出为:1 2 3 2 1
#include <vector>
#include <iostream>
#include <algorithm>
int main()
{
std::vector<int> v{2, 4, 2, 0, 5, 10, 7, 3, 7, 1};
std::cout << "before sort: ";
for(int n: v)
std::cout << n << ' ';
std::cout << '\n';
// insertion sort
for(auto i = v.begin(); i != v.end(); ++i)
{
std::rotate(std::upper_bound(v.begin(), i, *i), i, i+1);
}
std::cout << "after sort: ";
for(int n: v)
std::cout << n << ' ';
std::cout << '\n';
// simple rotation
std::rotate(v.begin(), v.begin() + 2, v.end());
std::cout << "simple rotation : ";
for(int n: v)
std::cout << n << ' ';
std::cout << '\n';
}
//输出为:
//before sort: 2 4 2 0 5 10 7 3 7 1
//after sort: 0 1 2 2 3 4 5 7 7 10
//simple rotation : 2 2 3 4 5 7 7 10 0 1
#include <algorithm>
#include <array>
#include <iostream>
#include <functional>
int main()
{
std::array<int, 10> s{5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
//将8替换为88
std::replace(s.begin(), s.end(), 8, 88);
for (int a : s) {
std::cout << a << " ";
}
std::cout << '\n';
//将小于5替换为55
std::replace_if(s.begin(),s.end(),std::bind(std::less<int>(), std::placeholders::_1, 5),55);
for (int a : s) {
std::cout << a << " ";
}
std::cout << '\n';
}
//output:
// 5 7 4 2 88 6 1 9 0 3
// 5 7 55 55 99 6 55 9 55 55
#include <algorithm>
#include <iostream>
#include <cstdlib>
int main()
{
std::vector<int> v(5);
// Using the C function rand()
std::generate(v.begin(), v.end(), std::rand);
std::cout << "v: ";
for (auto iv: v) {
std::cout << iv << " ";
}
std::cout << "\n";
}
//output:
// v: 52894 15984720 41513563 41346135 51451456
#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>
int main()
{
std::string in = "1234567890";
std::string out;
std::copy_n(in.begin(), 4, std::back_inserter(out));
std::cout << out << '\n';
}
//output:
//1234
#include <vector>
#include <iostream>
#include <algorithm>
int main(int argc, char** argv)
{
std::vector<int> v({1,2,3});
std::reverse(std::begin(v), std::end(v));
std::cout << v[0] << v[1] << v[2] << '\n';
int a[] = {4, 5, 6, 7};
std::reverse(&a[0], &a[4]);
std::cout << a[0] << a[1] << a[2] << a[3] << '\n';
}
//output:
//321
//7654