C++标准库常用算法小结

文档链接:http://www.cplusplus.com/reference/algorithm

总结记录一些常用的算法函数,更多信息参考文档文档链接

1.std::merge 合并序列

将两个序列中的元素合并高一个序列中,

  1. 序列中的元素必须是可比较的
  2. 默认两个序列中同位置上较小的元素会被排在前面,可以使用重载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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值