c++ STL 算法一

以下常用算法,来自经典书籍<<STL源码解析>>。

一、数值算法,标准库的仿函数一般用在此处。

accumutate()累加、 inner_product()内积、 partial_sum()相加、 adjacent_difference()相差 ,这些算法只能用在数值上,所以头文件是<numeric>.

另外还有mismatch().

int main()
{
	//accumulate() inner_product() partial_sum() adjacent_difference()

	int ia[5] = { 1,2,3,4,5 };
	vector<int> iv(ia, ia+5);
	
	//数值算法 <numeric>
	//仿函数   <functional>

	//累加(默认仿函数plus)  支持可调用对象(仿函数:plus minus multiplies divides modulus negate)
	cout<< accumulate(iv.begin(), iv.end(), 10) << endl;                    //10+1+2+3+4+5  
	cout << accumulate(iv.begin(), iv.end(), 10, minus<int>());             //10-1-2-3-4-5

	//两个序列相乘的和(默认参数)
	cout << inner_product(iv.begin(), iv.end(), iv.begin(), 10) << endl;   //10+1*1+2*2+3*3+4*4+5*5
	cout << inner_product(iv.begin(), iv.end(), iv.begin(), 10, minus<int>(), plus<int>()) << endl;   //10-1+1-2+2-3+3-4+4-5+5

	ostream_iterator<int> oiter(cout, " ");  //任意输入到此迭代器的都将输出到屏幕
	//等于前面数值相加
	//partial_sum(iv.begin(), iv.end(),iv.begin());             //1 3 6 10 15
	partial_sum(iv.begin(), iv.end(), oiter);                   //直接输出到屏幕
	partial_sum(iv.begin(), iv.end(), oiter,minus<int>());      //1 -1 -4 -8 -13
	cout << endl;

	//adjacent_difference() 与partial_sum() 互为逆运算

	//相邻元素的差 默认minus<>
	adjacent_difference(iv.begin(), iv.end(), oiter);              //1 1 1 1 1
	adjacent_difference(iv.begin(), iv.end(), oiter, plus<int>()); //1 2 3 7 9 相邻元素的和
	cout << endl;

	//mismatch equal 

	int ia1[9] = { 1,2,3,4,5,6,7,8,9 };
	vector<int> iv1(ia1, ia1 + 5);
	vector<int> iv2(ia1, ia1 + 9);

	//比较两个序列第一个不匹配的点,返回pair
	auto p_pair = mismatch(iv1.begin(), iv1.end(), iv2.begin(), iv2.end());
	if (p_pair.first == iv1.end())
		cout << "iv2包含iv1" << endl;
	else
		cout<<"iv1跟iv2 的第一个不同点在:"<< *(p_pair.first)<<endl;
	if (p_pair.second == iv2.end())
		cout << "iv1包含iv2" << endl;
	else
		cout << "iv2跟iv1 的第一个不同点在iv2的元素:" << *(p_pair.second) << endl;

}

二、fill、equal、advance、swap、lexicographical_compare、copy

int main()
{
    //equal返回bool  在[first,last)区间相等
	cout << equal(iv1.begin(), iv1.end(), iv2.begin()) << endl;  //1 iv2超长的部分不考虑,
																 //第二个序列一定不能比第一个短,否则是未定义行为
																 //所以要判断完全相等需要先判断队列长度
	cout << equal(iv1.begin(), iv1.end(), &ia1[3]) << endl;             //0
	cout << equal(iv1.begin(), iv1.end(), &ia1[3], less<int>()) << endl;//1 {1,2,3,4,5} 小于{3,4,5,6,7}

	//fill
	fill(iv1.begin(), iv1.end(), 9);
	fill_n(iv1.begin(), 3, 8);              //返回迭代器指向插入的下一个位置; 想想如果n超越了先有容器的大小会怎样
	fill_n(inserter(iv1,iv1.begin()), 8, 7);//是在头部插入8个7 ,这样就会自动扩容

	//for_each
	for_each(iv1.begin(), iv1.end(), [](int i) {cout << i << " "; });
	cout << endl;

	//advance
	vector<int>::iterator it1 = iv1.begin();
	vector<int>::iterator it2 = it1;
	advance(it2, 3);
	cout << *it2 << endl;

	//只对调元素 且只能通过迭代器 8 8 8 9 9 ->9 8 8 8 9  
	vector<int>::iterator it22 = iv2.begin();
	iter_swap(it1, it22);
	for_each(iv1.begin(), iv1.end(), [](int i) {cout << i << " "; });  //8 8 8 9 9 ->1 8 8 9 9
	cout << endl;
	for_each(iv2.begin(), iv2.end(), [](int i) {cout << i << " "; }); //1 2 3 4 5 6 7 8 9->9 2 3 4 5 6 7 8 9
	cout << endl;

	//值对调
	swap(*iv1.begin(), *iv2.begin());

	//对调序列 iv1 iv2对调,对调后原来的迭代器并不失效
	swap(iv1, iv2);
	for_each(iv1.begin(), iv1.end(), [](int i) {cout << i << " "; });  //1 8 8 9 9 -> 9 2 3 4 5 6 7 8 9
	cout << endl;
	for_each(iv2.begin(), iv2.end(), [](int i) {cout << i << " "; });  //9 2 3 4 5 6 7 8 9-> 1 8 8 9 9
	cout << endl;
	


	//字符串序列比较
	vector<string> start1{ "Jamie","JJHou","Jason" };
	vector<string> start2{ "Jamie","JJHou","Jeson" };

	cout << lexicographical_compare(start1.begin(), start1.end(), start2.begin(), start2.end()) << endl; //1  start1<start2
	cout << lexicographical_compare(start1.begin(), start1.end(), start2.begin(), start2.end(), greater<string>()) << endl; //0  start1 不大于 start2
	
	//只是获取两个数的最大\最小,而且只能作用于数值类型 ,用途不大;获取序列的最大、最小用途更广
	cout << max(*iv1.begin(), *iv2.begin()) << endl;
	cout << min(*iv1.begin(), *iv2.begin()) << endl;

	cout << "============================" << endl;
	//copy 为了效率 copy的实现相当复杂
	int ca[8] = { 0,1,2,3,4,5,6,7 };
	
	
	//注意这是目标起始位置,在输入数据中间,这种情况很可能会出问题,要慎用
	//这里之所以没出问题 (vector起始也不出问题),是因为copy内部的特殊处理,用memmove直接复制了输入的内存,
	//进行拷贝的,而如果用list 、deque等是一个元素一个元素的拷贝,就会出问题
	auto it =copy(ca + 2, ca + 6, ca + 3);  //0,1,2,2,3,4,5,7

	//这里换成deque就不是我们预期的结果
	//deque<int> de{ 0,1,2,3,4,5,6,7 };
	//auto it = copy(de.begin() + 2, de.begin() + 6, de.begin() + 3);  //0 1 2 2 2 2 2 7

	//所以copy()目标位置的开通不能在输入区间,但结尾可以在输入区间,copy_backward相反

	char cha[] = { 'a','b','c','d','e','f','g' };
	char cha2[8] = { 0 };
	copy_backward(cha, cha + 7, cha2+7); //a b c d e f g
	
	for (auto i : cha2)
		printf("%c ", i);


	
	return 0;

}

三、set中用到的并、交、差

set的运算和我们正常理解是一样的,multiset的运算稍微有点差异。

int ar1[] = { 1,3,5,7,9,11 };
	int ar2[] = { 1,1,2,3,5,8,13 };
	multiset<int> s1(ar1, ar1 + 6);
	multiset<int> s2(ar2, ar2 + 7);

	multiset<int>::iterator first1 = s1.begin();
	multiset<int>::iterator last1 = s1.end();
	multiset<int>::iterator first2 = s2.begin();
	multiset<int>::iterator last2 = s2.end();

	//并集
	cout << "Union of s1 and s2: ";
	set_union(first1, last1, first2, last2, ostream_iterator<int>(cout, " "));     //并集 出现在s1和s2 则以s1为准,
	cout << endl;                                                           因为元素不唯一,s1中出现n次,s2中出现m次,并后为max(n,m)

	//交集
	cout << "difference of s1 and s2: ";
	set_intersection(first1, last1, first2, last2, ostream_iterator<int>(cout, " "));
	cout << endl;

	//差集
	cout << "difference of s1 and s2: ";
	set_difference(first1, last1, first2, last2, ostream_iterator<int>(cout, " "));//差集不唯一的元素 min(n,m)
	cout << endl;

	//对称差集
	cout << "symmetric_difference of s1 and s2: ";  //对称差集,在s1中不在s2中,及在s2中不在s1中
	set_symmetric_difference(first1, last1, first2, last2, ostream_iterator<int>(cout, " ")); //abs(n-m)
	cout << endl;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值