文档链接:http://www.cplusplus.com/reference/algorithm
目录
总结记录一些常用的算法函数,更多信息参考文档文档链接
1.std::merge 合并序列
将两个序列中的元素合并高一个序列中,
- 序列中的元素必须是可比较的
- 默认两个序列中同位置上较小的元素会被排在前面,可以使用重载custom (2)传入定制的谓词
#include<algorithm>
#include<iostream>
#include<vector>
#include<functional>
using namespace std;
/*
default (1)
template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator merge (InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
OutputIterator result);
custom (2)
template <class InputIterator1, class InputIterator2,
class OutputIterator, class Compare>
OutputIterator merge (InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
OutputIterator result, Compare comp);
*/
std::function<void(vector<int> v)> dump = [=](vector<int> v) {
for (auto it=v.begin();it!=v.end();++it)
{
cout << *it << " ";
}
cout << endl;
};
template<typename input_iterator1,typename input_iterator2,typename out_iterator >
out_iterator my_merge(input_iterator1 t1_begin, input_iterator1 t1_end, input_iterator2 t2_begin, input_iterator2 t2_end, out_iterator out_begin)
{
while (true) {
//一方面如果一个列表一开始就是空的,就拷贝另一个列表;另一方面,如果两个列表的长度不一致,当一个列表循环处理完后,
//将另一个列表的剩余部分拷到最后的结果中
if (t1_begin==t1_end)
{
return std::copy(t2_begin, t2_end, out_begin);
}
if (t2_begin == t2_end)
{
return std::copy(t1_begin, t1_end, out_begin);
}
//*out_begin++ 运算顺序是先计算迭代器,然后再解引用,加括号后: *(out_begin++)
*(out_begin++) = (*t1_begin < *t2_begin) ? *(t1_begin++) : *t2_begin++;
}
}
int main()
{
vector<int> v1 = { 1,3,7,5,9 };
vector<int> v2 = { 2,10,6,8,4 };
vector<int> result;
result.resize(v1.size() + v2.size());
std::sort(v1.begin(), v1.end());
std::sort(v2.begin(), v2.end());
dump(v1); dump(v2);
//std::merge(v1.begin(), v1.end(), v2.begin(), v2.end() , result.begin());
my_merge(v1.begin(), v1.end(), v2.begin(), v2.end(), result.begin());
dump(result);
system("pause");
return 0;
}
2.std::partition 分割序列
这个函数将序列按照传入的谓词规则进行分割,符合谓词条件的会放在序列的前面,不符合条件的放在序列的后面,返回边界的迭代器
#include<algorithm>
#include<iostream>
#include<vector>
#include<functional>
using namespace std;
/*
函数原型
template <class ForwardIterator, class UnaryPredicate>
ForwardIterator partition (ForwardIterator first,
ForwardIterator last, UnaryPredicate pred);
return value:保留的是表达式为true的部分
An iterator that points to the first element of the second group of elements (those for which pred returns false), or last if this group is empty.
*/
//思路从序列开头去找能使谓词返回false的第一个元素f1,从序列结尾开始去找能使谓词返回为true的第一个元素t1,找到后交换f1,t1直到 first == last 为止并返回first
template<class BidirectionalIterator,class UnaryPredicate/*一元谓词*/>
BidirectionalIterator my_partition(BidirectionalIterator first, BidirectionalIterator last, UnaryPredicate pred) {
while (first != last) {
while (pred(*first)) {
++first;
if (first == last)
return first;
}
do {
--last;
if (first == last)
return first;
} while (!pred(*last));
swap(*first, *last);
++first;
}
return first;
}
std::function<void(vector<int> v)> dump = [=](vector<int> v) {
for (auto it = v.begin(); it != v.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
};
int main()
{
vector<int> v = { 1,2,3,4,5,6,7,8,9,10 };
dump(v);//1 2 3 4 5 6 7 8 9 10
//放回的是分割后的边界
/*vector<int>::iterator bound = std::partition(v.begin(), v.end(), [=](int i) {
return i%2 == 1;
});*/
vector<int>::iterator bound = my_partition(v.begin(), v.end(), [=](int i) {
return i % 2 == 1;
});
dump(v);//1 9 3 7 5 6 4 8 2 10 partition是把表达式为true的放在容器前面
// print out content:
std::cout << "odd elements:";
for (std::vector<int>::iterator it = v.begin(); it != bound; ++it)
std::cout << ' ' << *it;
std::cout << '\n';
std::cout << "even elements:";
for (std::vector<int>::iterator it = bound; it != v.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
//odd elements : 1 9 3 7 5
//even elements : 6 4 8 2 10
system("pause");
return 0;
}
3.partition_copy分割序列,并拷贝到新序列中
// partition_copy example
#include <iostream> // std::cout
#include <algorithm> // std::partition_copy, std::count_if
#include <vector> // std::vector
bool IsOdd (int i) { return (i%2)==1; }
int main () {
std::vector<int> foo {1,2,3,4,5,6,7,8,9};
std::vector<int> odd, even;
// resize vectors to proper size:
unsigned n = std::count_if (foo.begin(), foo.end(), IsOdd);
odd.resize(n); even.resize(foo.size()-n);
// partition:
std::partition_copy (foo.begin(), foo.end(), odd.begin(), even.begin(), IsOdd);
// print contents:
std::cout << "odd: "; for (int& x:odd) std::cout << ' ' << x; std::cout << '\n';
std::cout << "even: "; for (int& x:even) std::cout << ' ' << x; std::cout << '\n';
return 0;
}
odd: 1 3 5 7 9
even: 2 4 6 8
4.partition_point分割并返回分割点
partition_point返回分割点后可通过assign方法赋值给新的序列
//例子中的序列为 std::vector<int>
auto it = std::partition_point(foo.begin(),foo.end(),IsOdd);
odd.assign (foo.begin(),it);
5.replace 替换序列中某个元素
int myints[] = { 10, 20, 30, 30, 20, 10, 10, 20 };
std::vector<int> myvector (myints, myints+8); // 10 20 30 30 20 10 10 20
std::replace (myvector.begin(), myvector.end(), 20, 99); // 10 99 30 30 99 10 10 99
等效的源码实现为:
template <class ForwardIterator, class T>
void replace (ForwardIterator first, ForwardIterator last,
const T& old_value, const T& new_value)
{
while (first!=last) {
if (*first == old_value) *first=new_value;
++first;
}
}
6.replace_copy 替换并拷贝到新容器
int myints[] = { 10, 20, 30, 30, 20, 10, 10, 20 };
std::vector<int> myvector (8);
std::replace_copy (myints, myints+8, myvector.begin(), 20, 99);
//myvector contains: 10 99 30 30 99 10 10 99
7. find_if 返回第一个符合条件的元素位置
std::vector<int> myvector={10,25,40,55};
std::vector<int>::iterator it = std::find_if (myvector.begin(), myvector.end(), IsOdd);
std::cout << "The first odd value is " << *it << '\n';//25
8. shuffle 打乱序列
// shuffle algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::shuffle
#include <array> // std::array
#include <random> // std::default_random_engine
#include <chrono> // std::chrono::system_clock
int main () {
std::array<int,5> foo {1,2,3,4,5};
// obtain a time-based seed:
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
shuffle (foo.begin(), foo.end(), std::default_random_engine(seed));
std::cout << "shuffled elements:";
for (int& x: foo) std::cout << ' ' << x;
std::cout << '\n';
return 0;
}
9. unique “去除”容器或者数组中相邻元素的重复出现的元素
该函数的作用是“去除”容器或者数组中相邻元素的重复出现的元素,注意
(1) 这里的去除并非真正意义的erase,而是将重复的元素放到容器的末尾,返回值是去重之后的尾地址。
(2) unique针对的是相邻元素,所以对于顺序顺序错乱的数组成员,或者容器成员,需要先进行排序,可以调用std::sort()函数
常和sort一起用来去重
#include <iostream> // std::cout
#include <algorithm> // std::unique, std::distance
#include <vector> // std::vector
bool myfunction(int i, int j) {
return (i == j);
}
int main() {
int myints[] = { 10, 20, 20, 20, 30, 30, 20, 20, 10 }; // 10 20 20 20 30 30 20 20 10
std::vector<int> myvector(myints, myints + 9);
std::sort(myvector.begin(), myvector.end()); //10 10 20 20 20 20 20 30 30
// using default comparison:
std::vector<int>::iterator it;
it = std::unique(myvector.begin(), myvector.end());
myvector.resize(std::distance(myvector.begin(), it)); // 10 20 30
// using predicate comparison:
std::unique(myvector.begin(), myvector.end(), myfunction); // (no changes)
// print out content:
std::cout << "myvector contains:";
for (it = myvector.begin(); it != myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
system("pause");
return 0;
}