C++学习笔记-STL中的算法

1,STL算法简介

100多种算法
函数对象(function objects)
函数适配器(function adapters)
三个头文件:<algorithm>, <numeric>, <functional>
预定义的函数对象:

函数对象用法示例及解释
negate<type>()取负操作
plus<type>()加法操作
minus<type>()减法操作
multiplies<type>()乘法操作
divides<type>()除法操作
modulus<type>()vector<int>::iterator it = find_if(v.begin(), v.end(), not1(bind2nd(modulus<int>(), 3)));取模操作;对容器中每一个元素除3区余数,not1表示取反;该语句含义为查找容器v中第一个能被3整除的数。
equal_to<type>()等于
not_equal_to<type>()不等于
less<type>()小于
greater<type>()vector::iterator it = find_if(v.begin(), v.end(), bind2nd(greater<int>(), 3))); 该语句含义为查找容器v中第一个大于3数。(下面less_equal,greater_equal同理)
less_equal<type>()小于等于
greater_equal<type>()大于等于
logical_not<type>()逻辑非
logical_and<type>()逻辑与
logical_or<type>()逻辑或

预定义的函数适配器

函数适配器示例及解释(下面op为函数对象,value为传入的参数)
bind1st(op, value)
bind2nd(op, value)解释见上表
not1(op)取反,解释间上表
not2(op)
mem_fun_ref(op)
mem_fun(op)
ptr_fun(op)

算法分类:

  1. 非修改性算法(nonmodifying algorithms),不会修改容器中数据的内容
方法解释
for_each(b, e, 操作);对迭代器b到e之间的所有元素执行某操作
count(b, e, n);返回迭代器b到e之间的所有元素中n的个数
count_if(b, e, 谓词);返回迭代器b到e之间满足谓词逻辑的所有元素个数
min_element(b, e);返回指向元素最小值的迭代器
max_element(b, e);返回指向元素最大值的迭代器
find();查找等于某值的第一个元素
find_if();查找满足某个条件的第一个元素
search();查找某个子区间第一次出现的位置
search_n(b, e, n, val);在迭代器b到e区间查找是否有n个连续的值为val 的元素,若找到,返回指向连续n个val值中的第一个val的元素位置,否则值为container.end()
search_n(b, e, n, val, 谓词);在迭代器b到e区间查找是否有n个连续的满足谓词条件的元素,若找到,返回指向连续n个val值中的第一个val的元素位置,否则值为container.end()
find_end();查找某个区间最后一次出现的位置
find_fisrt_of();查找等于“某数个值之一”的第一个元素
adjacent_find();搜寻连续两个符合特定准则的元素
equal();判断两区间是否相等
mismatch();返回两个序列的各组对应元素中第一对不相等元素
lexicographical_compare();判断某一序列在“字典顺序(lexicographically)”下是否小于另一序列。
  1. 修改性算法(modifying algorithms)
方法解释
for_each();
copy();从第一个元素开始,复制某段区间
copy_backward();从最后一个元素开始,复制某一段区间
transform();将两个区间的元素合并
merge();合并两个区间
swap_ranges();交换两个区间的元素
fill();以给定值替换每一个元素
fill_n();以给定值替换n个元素
generate();以某项操作的结果替换每一个元素
generate_n();以某项操作的结果替换n个元素
replace();将某项特定值的元素替换为另一元素
replace_if();将符合某条件的元素替换为另一元素
replace_copy();复制整个区间,同时并将具有某特定值的元素替换为另一元素
replace_copy_if();复制整个区间,同时并将符合特定条件的元素替换为另一元素
  1. 移除性算法(removing algorithms)
方法解释
remove();将某特定值的元素全部移除
remove_if();将满足某准则的元素全部移除
remove_copy();将不等于某特定值的元素全部复制
remove_copy_if();将不满足某特定条件的元素全部复制
unique();移除毗邻的重复元素
unique_copy();移除毗邻的元素并复制
  1. 变序性算法(mutating algorithms)
方法解释
reverse();将元素逆序
reverse_copy();复制元素,然后逆序
rotate();旋转元素次序
rotate_copy();得到元素的下一个排列次序
next_permutation();得到元素的上一个排列次序
prev_permutation();得到元素的下一个排列次序
random_shuffle();将元素的次序随机打乱
partition();改变元素次序,使“符合某准则”者移到前面
stable_partition();与partition()相似,但保持符合条件和不符该合条件的各个元素之间的相对位置
  1. 排序性算法(sorting algorithms)
方法解释
sort();对所有元素排序
stable_sort();对所有元素排序,并保持相等元素间的相对次序排序,
partial_sort();排序,直到n个元素就位,
partial_sort_copy();排序,直到n个元素就位,并复制结果
nth_element();根据第n个位置进行排序
partition();改变元素次序,使符合某准则的元素放在前面
stable_partition();与partition()相似,但保持符合条件和不符该合条件的各个元素之间的相对位置
make_heap();将一个区间转换成heap
push_heap();将元素加入一个heap
pop_heap();从heap中移除一个元素
sort_heap();对heap进行排序(执行后不再是heap了)
  1. 已序区间算法(sorted range algorithms),在已经排序的基础上对容器中的元素执行操作。
方法解释
binary_search();判断某区间是否包含某个元素
include();判断某区间内的每一个元素是否都涵盖于另一个区间中
lower_bound();查找第一个大于给定值的元素
upper_bound();查找第一个小于给定值的元素
equal_range();返回等于给定值的所有元素构成的区间
merge();将两个区间的元素合并
set_unique();求两区间并集
set_intersection();将两区间交集
set_difference();求位于第一区间但不位于第二区间的元素,形成一个已序区间
set_symmetric_difference();找出出现于两区间的所有元素,形成一个已序区间
inplace_merge();将两个连续的已序区间合并
  1. 数值算法(numeric algorithms)
方法解释
accumulate();求和
inner_product();组合区间内所有元素
adjacent_difference();将每个元素和前一元素组合
partial_sum();将每个元素和其先前的所有元素组合

2,方法

2.1 count 和 count_if 方法

count和count_if对所有容器都是用,是用线性的方法查找,但对于关联容器set和map,有其内部的成员函数:set.count(); multiset.count(); map.count(); multimap.count();它们的速度比通用的count和count_if更快。

#include<iostream>
#include<vector>
#include<set>
#include<algorithm>
#include<functional>

void printValue(int val)
{
	std::cout << val << " ";
}
bool isEven(int val)
{
	return val % 2 == 0;
}


int main()
{
	std::vector<int> vis;
	vis.push_back(1); vis.push_back(3); vis.push_back(5); vis.push_back(7);
	vis.push_back(1); vis.push_back(4); vis.push_back(7); vis.push_back(1);
	std::cout << "容器vis中所有元素:";
	for_each(vis.begin(), vis.end(), printValue);
	std::cout << std::endl;
	int vc = count(vis.begin(), vis.end(), 1); // count函数在algorithm头文件中;
	std::cout << "容器vis中1的个数:" << vc << std::endl;

	vc = count_if(vis.begin(), vis.end(), isEven); // count_if函数在algorithm头文件中;
	std::cout << "容器vis中偶数个数:" << vc << std::endl;
	//  bind2nd为函数适配器,modulus<int>()函数对象(有两个参数,param1 % param2),param1从迭代器传入,param2人为设定(设为2)
	// 下面含义为计数vis容器中奇数(param1 % 2 为1(true))个数
	vc = count_if(vis.begin(), vis.end(), std::bind2nd(std::modulus<int>(), 2)); // count_if函数在algorithm头文件中;
	std::cout << "容器vis中奇数个数:" << vc << std::endl;
	vc = count_if(vis.begin(), vis.end(), std::not1(std::bind2nd(std::modulus<int>(), 2))); // count_if函数在algorithm头文件中;
	std::cout << "容器vis中偶数数个数:" << vc << std::endl;

	//  bind2nd为函数适配器,greater<int>()函数对象(有两个参数,param1 > param2),param1从迭代器传入,param2人为设定(设为3)
	// 下面含义为计数vis容器中满足大于3的元素个数
	vc = count_if(vis.begin(), vis.end(), std::bind2nd(std::greater<int>(), 3)); //函数适配器bind2nd 在functional头文件中;
	std::cout << "容器vis中大于3的元素个数:" << vc << std::endl;
	 
	std::multiset<int> mset(vis.begin(), vis.end());
	vc = count(mset.begin(), mset.end(), 4);
	std::cout << "容器mset中4的个数:" << vc << std::endl;
	vc = mset.count(4);
	std::cout << "容器mset中4的个数:" << vc << std::endl;

	//system("pause");
	return 0;
}
2.2 max_element 和 min_element 方法

max_element(b, e);
max_element(b, e, op);
min_element(b, e);
min_element(b, e, op);

#include<iostream>
#include<deque>
#include<algorithm>
//#include<functional>

bool absCompare(int val1, int val2)
{
	return abs(val1) < abs(val2);
}

int main()
{
	std::deque<int> dq;
	for (int i = -15; i <= 9; ++i) dq.push_back(i);
	std::cout << "容器dq中的内容:";
	for (int i = 0; i < dq.size(); ++i) std::cout << dq[i] << " "; std::cout << std::endl;
	std::cout << "容器dq中最小值为:" << *min_element(dq.begin(), dq.end()) << std::endl;
	std::cout << "容器dq中最大值为:" << *max_element(dq.begin(), dq.end()) << std::endl;
	std::cout << "容器dq中绝对最小值为:" << *min_element(dq.begin(), dq.end(), absCompare) << std::endl;
	std::cout << "容器dq中绝对最大值为:" << abs(*max_element(dq.begin(), dq.end(), absCompare)) << std::endl;

	//system("pause");
	return 0;
}
2.3 查找算法

find(); find_if(); search(); search_n(); find_end(); find_first_of(); adjacent_find() 方法

  1. find和find_if方法:对所有的容器都是用,是线性的查找算法。 如果对于已序区间,是用相应的已序区间查找算法(binary_search(); includes(); lower_bound(); upper_bound();)更快。 对于关联式容器有等效的成员函数find(),比上述两种通用find方法更合适。 string类型用自己的成员函数find();
  2. search_n;find_end和search方法
  3. find_first_of(b, e, sb, se); find_first_of(b, e, sb, se, bp);没有find_last_of,可通过逆向迭代器实现find_last_of的功能。
  4. adjacent_find(b, e)和adjacent_find(b, e, p)分别用来查找连续的两个相等的和连续两个符合谓词p规则的元素位置。如果对于已序区间,是用相应的已序区间查找算法(binary_search(); includes(); lower_bound(); upper_bound();)更快。 上面7种方法都是线性查找算法。
  5. binary_search(b,e,sb,se)和includes(b, e, sb, se)方法
  6. lower_bound; upper_bound(); equal_bound();方法,对于关联容器,有其内部的对应成员函数,用其内部的成员函数更合适。
#include<iostream>
#include<list>
#include<vector>
#include<deque>
#include<set>
#include<string>
#include<algorithm>
#include<functional>

template <typename Container>
void printContainer(const Container& con, std::string str)
{
	std::cout << "--------------------------------\n"<< str;
	for (Container::const_iterator it = con.begin(); it != con.end(); ++it)
		std::cout << *it << " ";
	std::cout << std::endl;
}

bool checkEven(int val, bool flag)  // 若flag为true,检查val是否为偶数;否则检查其时候为奇数;
{
	if (flag) return val % 2 == 0;
	else return val % 2 == 1;
}

bool myAdjacent(int val1, int val2)
{
	return val1 * 1.5 == val2;
}

int main()
{
	std::list<int> lst;
	for (int i = 0; i <= 9; ++i) lst.push_back(i);
	for (int i = 0; i <= 9; ++i) lst.push_back(i);
	printContainer(lst, "容器lst中的元素:"); // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
	// *********************** find ***********************
	// 输出lst中两个4之间的所有数据
	std::list<int>::iterator pos1 = find(lst.begin(), lst.end(), 4);
	std::list<int>::iterator pos2 = find(++pos1, lst.end(), 4);
	--pos1; ++pos2;
	for (std::list<int>::iterator iter = pos1; iter != pos2; ++iter) std::cout << *iter << " ";
	std::cout << std::endl;  // 4 5 6 7 8 9 0 1 2 3 4
	// *********************** find_if ***********************
	std::vector<int> vt(++lst.begin(), --lst.end()); 
	for (std::vector<int>::const_iterator iter = vt.begin(); iter != vt.end(); ++iter) std::cout << *iter << " ";
	std::cout << std::endl;  // 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8
	std::vector<int>::iterator pos = find_if(vt.begin(), vt.end(), std::bind2nd(std::greater<int>(), 3));
	std::cout << "容器vt中第一个大于3的数为:" << *pos << std::endl;
	pos = find_if(vt.begin(), vt.end(), std::not1(std::bind2nd(std::modulus<int>(), 3)));
	std::cout << "容器vt中第一个能被3整除的数为:" << *pos << std::endl;

	std::set<int> st(vt.begin(), vt.end()); // set容器适配器(或关联容器),不允许元素重复,自动排序。
	printContainer(st, "容器st中的元素:"); // 0 1 2 3 4 5 6 7 8 9
	std::cout << *find(st.begin(), st.end(), 4) << "在容器st中。\n"; // 对所有容器通用find方法,线性查找,速度慢
	std::cout << *st.find(5) << "在容器st中。\n";  // 关联容器内部find方法,二分查找,速度快

	std::string str("Hello C++ World");
	std::cout << str << std::endl;
	std::string::size_type p = str.find("C++");
	if (p != std::string::npos)  
		std::cout << "找到C++,开始字符为:" << str[p] << " ,下标为:" << p << std::endl;
	else
		std::cout << "没有找到!" << std::endl;

	// *********************** search_n ***********************
	std::deque<int> dq(vt.begin(), vt.end());
	dq.push_back(3); dq.push_back(3); dq.push_back(1);
	sort(dq.begin(), dq.end());
	printContainer(dq, "容器dq中的元素:"); // 0 1 1 1 2 2 3 3 3 3 4 4 5 5 6 6 7 7 8 8 9
	std::deque<int>::iterator pos3 = search_n(dq.begin(), dq.end(), 3, 1);
	if (pos3 != dq.end())
		std::cout << "找到连续的3个1,起始下标为:" << std::distance(dq.begin(), pos3) << std::endl;
	pos3 = search_n(dq.begin(), dq.end(), 5, 6, std::greater<int>()); // 注意,此处写法不符合STL规范,历史原因造成的,记住即可;
	//pos3 = search_n_if(dq.begin(), dq.end(), 5, std::bind2nd(std::greater<int>(), 6)); //**这种写法更符合规范,但历史原因,是错误的
	if(pos3 != dq.end())
		std::cout << "找到连续的5个大于6的数,起始下标为:" << pos3 - dq.begin() << std::endl; // pos3 - dq.begin()这种方式仅适用于可通过下标索引访问的容器
	
	// *********************** search ***********************
	printContainer(lst, "now, 容器lst中的元素:"); // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
	printContainer(st, "now, 容器st中的元素:"); // 0 1 2 3 4 5 6 7 8 9
	printContainer(dq, "now, 容器dq中的元素:"); // 0 1 1 1 2 2 3 3 3 3 4 4 5 5 6 6 7 7 8 8 9
	std::list<int>::iterator poslist = search(lst.begin(), lst.end(), st.begin(), st.end());
	if (poslist != lst.end())
		std::cout << "容器st区间在lst区间中,起始位置位:" << std::distance(lst.begin(), poslist) << std::endl;
	std::deque<int>::iterator posdeque = search(dq.begin(), dq.end(), st.begin(), st.end());
	if (posdeque != dq.end())
		std::cout << "容器st区间在lst区间中,起始位置位:" << std::distance(dq.begin(), posdeque) << std::endl;
	else
		std::cout << "容器st区间不在在dq区间\n";
	bool flags[] = { true, false, true };
	//或者:std::vector<bool> flags = {true, false, true}; 下面flag, flag+3改为flag.begin(), flag.end()
	std::set<int>::iterator posset = search(st.begin(), st.end(), flags, flags + 3, checkEven);
	if (posset != st.end())
		std::cout << "在容器st中存在 偶数-奇数-偶数(true,false,true) 的序列,起始位置为:" << std::distance(st.begin(), posset) << std::endl; // 不能使用这种方式:posset - st.begin()
	std::vector<bool> vflag = { true, true, false, false };
	posdeque = search(dq.begin(), dq.end(), vflag.begin(), vflag.end(), checkEven);
	if (posdeque != dq.end())
		std::cout << "在容器dq中存在 偶数-偶数-奇数-奇数(true,true,false,false) 的序列,起始位置为:" << posdeque - dq.begin() << std::endl; // <==>std::distance(dq.begin(), posdeque)
	// *********************** find_end (与search对应,找满足条件的最后一个) ***********************
	poslist = find_end(lst.begin(), lst.end(), st.begin(), st.end());
	if (poslist != lst.end())
		std::cout << "容器st区间在lst区间中,起始位置位:" << std::distance(lst.begin(), poslist) << std::endl;
	posdeque = find_end(dq.begin(), dq.end(), st.begin(), st.end());
	if (posdeque != dq.end())
		std::cout << "容器st区间在lst区间中,起始位置位:" << std::distance(dq.begin(), posdeque) << std::endl;
	else
		std::cout << "容器st区间不在在dq区间\n";

	// *********************** find_first_of ***********************
	printContainer(st, "now, 容器st中的元素:"); //  0 1 2 3 4 5 6 7 8 9
	std::vector<int> find_list = { 3,5,7 };
	std::set<int>::iterator spos = find_first_of(st.begin(), st.end(), find_list.begin(), find_list.end());
	if (spos != st.end())
		std::cout << "find_list容器中存在某元素也在st容器中,下标为:" << distance(st.begin(), spos) << std::endl;
	std::set<int>::reverse_iterator rspos = find_first_of(st.rbegin(), st.rend(), find_list.begin(), find_list.end()); // 逆向查找需要使用逆向迭代器reverse_iterator
	if (spos != st.end())
		std::cout << "find_list容器中存在某元素也在st容器中,下标为:" << distance(st.begin(), rspos.base()) - 1 << std::endl; // 使用distance方法时,需要经rspos转化为正向迭代器,由于转变过程中的机制,需要再减1
	// 对于string类型,有find_first_of 和 find_last_of两种迭代器,而其它容器只有find_first_of一种方法,但可通过逆向迭代器实现find_last_of的功能。
	// string类型的find_first_of 请参考:https://blog.youkuaiyun.com/sunqin_csdn/article/details/85028480

	// *********************** adjacent_find ***********************
	printContainer(dq, "now, 容器dq中的元素:"); // 0 1 1 1 2 2 3 3 3 3 4 4 5 5 6 6 7 7 8 8 9
	std::deque<int>::iterator dpos = adjacent_find(dq.begin(), dq.end());
	if (dpos != dq.end())
		std::cout << "找到dq容器中第一组连续两个相等的元素,下标为:" << dpos - dq.begin() << std::endl;
	std::deque<int>::reverse_iterator rdpos = adjacent_find(dq.rbegin(), dq.rend());
	if (rdpos != dq.rend())
		std::cout << "找到dq容器中最后一组连续两个相等的元素,下标为:" << distance(dq.begin(), rdpos.base()) - 1 << std::endl;
	dpos = adjacent_find(dq.begin(), dq.end(), myAdjacent);
	if (dpos != dq.end())
		std::cout << "找到dq容器满足adjacent逻辑的一组元素,下标为:" << distance(dq.begin(), dpos) << std::endl;

	// ********** 已序区间算法:binary_search, includes, lower_bound, upper_bound, equal_bound
	// *********************** binary_search ***********************
	printContainer(dq, "now, 容器dq中的元素:"); // 0 1 1 1 2 2 3 3 3 3 4 4 5 5 6 6 7 7 8 8 9
	if(binary_search(dq.begin(), dq.end(), 5))   // binary_search方法只能查找元素是否存在,无法得到找到的元素的位置
		std::cout << "元素5在容器dq中\n"; 
	// *********************** includes ***********************
	if (includes(dq.begin(), dq.end(), find_list.begin(), find_list.end())) // includes方法返回是否找到,find_list需要有序,只有其中的所有元素都被找到,才返回true;
		std::cout << "容器find_list中的所有元素都存在于dq容器中。\n";
	// *********************** lower_bound ***********************
	dpos = lower_bound(dq.begin(), dq.end(), 3);
	if (dpos != dq.end())
		std::cout << "容器dq中第一个3的位置为:" << distance(dq.begin(), dpos) << std::endl;
	// *********************** upper_bound ***********************
	dpos = upper_bound(dq.begin(), dq.end(), 3);
	if (dpos != dq.end())
		std::cout << "容器dq中最后一个3的下一个位置为:" << distance(dq.begin(), dpos) << std::endl;
	// *********************** equal_bound *********************** // 等效于lower_bound和upper_bound
	std::pair<std::deque<int>::iterator, std::deque<int>::iterator> dpos12;
	dpos12 = equal_range(dq.begin(), dq.end(), 3);
	std::cout << "容器dq中第一个3的位置为:" << distance(dq.begin(), dpos12.first) << std::endl;
	std::cout << "容器dq中最后一个3的下一个位置为:" << distance(dq.begin(), dpos12.second) << std::endl;
	// 对于关联式容器,有其内部的成员函数可用,速度更快。
	std::multiset<int> mst(dq.begin(), dq.end());
	printContainer(mst, "now, 容器mst中的元素:"); // 0 1 1 1 2 2 3 3 3 3 4 4 5 5 6 6 7 7 8 8 9
	std::multiset<int>::iterator mpos = mst.lower_bound(5);
	std::cout << "容器mst中第一个5的位置为:" << distance(mst.begin(), mpos) << std::endl;

	//system("pause");
	return 0;
}
2.4 for_each方法
#include<iostream>
#include<vector>
#include<algorithm>

template <typename Container>
void printContainer(const Container& con, std::string str)
{
	std::cout << str.c_str();
	for (Container::const_iterator it = con.begin(); it != con.end(); ++it)
		std::cout << *it << " ";
	std::cout << std::endl;
}

void printContent(int elem)
{
	std::cout << elem << " ";
}

template <typename T>
class addValue
{
private:
	T the_value;
public:
	addValue(const T& v):the_value(v) {}
	void operator() (T& elem) const
	{
		elem += the_value;
	}
};

class getMeanValue
{
private:
	long sum;
	long count;
public:
	getMeanValue() :sum(0), count(0) {}
	void operator() (int elem)
	{
		sum += elem;
		count++;
	}
	double value()
	{
		return static_cast<double>(sum) / static_cast<double>(count);
	}
	operator double()
	{
		return static_cast<double>(sum) / static_cast<double>(count);
	}
};

int main()
{
	std::vector<int> vt = { 1,2,3,4,5,6,7,8,9 };
	printContainer(vt, "容器vt中的元素为:"); // for_each(vt.begin(), vt.end(), printContent); std::cout << std::endl;
	for_each(vt.begin(), vt.end(), addValue<int>(*(--vt.end())));
	printContainer(vt, "now,容器vt中的元素为:");
	for_each(vt.begin(), vt.end(), addValue<int>(10));
	printContainer(vt, "now,容器vt中的元素为:");
	getMeanValue gmv = for_each(vt.begin(), vt.end(), getMeanValue());  // 类getMeanValue的返回值其对象,通过相应的函数得到平均值;
	std::cout << "now,容器均值为:" << gmv.value() << std::endl;
	double mv = for_each(vt.begin(), vt.end(), getMeanValue());   // 其返回值仍然为getMeanValue的对象,但被operator double()进行强制类型转换为double类型,故可以用double类型变量来接受;
	std::cout << "now,容器均值为:" << mv << std::endl;

	//system("pause");
	return 0;
}
2.5 transform 方法

transform(b1, e1, b2, op),将源区间b1和e1之间的元素经过op操作再插入到目标b2区间中。
transform(b1,e1,b2,b3,op),将源区间b1和e1区间的元素和b2间的元素进行op操作后插入到目标b3区间中。
for_each(), 其谓词传递引用,无返回值,速度快,但不灵活。
transform(),其谓词传递拷贝,有返回值,速度慢,非常灵活。
注意:

  1. 如果目标与源相同,则transform()和for_each()一样。
  2. 如果想以某值替代符合规则的元素,应使用replace()算法。
#include<iostream>
#include<vector>
#include<list>
#include<algorithm>
#include<functional>
#include<iterator>

template <typename Container>
void printContainer(const Container& con, std::string str)
{
	std::cout << str.c_str();
	for (Container::const_iterator it = con.begin(); it != con.end(); ++it)
	{
		std::cout << *it << " ";
	}
	std::cout << std::endl;
}

void mySqrt(int& elem)  // 充当for_each的谓词,必须要是引用,修改elem相当于直接修改传入容器元素的值;由于传递应用,故速度很快
{
	elem = sqrt(elem);
}

int mySquare(int elem)  // 充当transform的谓词,传递的不是引用,而是其拷贝,有返回值,故速度较慢
{
	return elem * elem;
}

int main()
{
	// ****************** transform(b1, e1, b2, op) ******************
	std::vector<int> vt = { 1,2,3,4,5,6,7,8,9 };
	printContainer(vt, "now, 容器vt中的内容为:");  // 1 2 3 4 5 6 7 8 9
	transform(vt.begin(), vt.end(), vt.begin(), std::negate<int>()); // transform函数在<algorithm>头文件中,negate函数在<functional>头文件中
	printContainer(vt, "now, 容器vt中的内容为:");  // -1 -2 -3 -4 -5 -6 -7 -8 -9

	std::list<int> lst;
	transform(vt.begin(), vt.end(), back_inserter(lst), std::bind2nd(std::multiplies<int>(), 10));  //使用back_inserter方法, ×10后的结果插入到lst的后面
	printContainer(lst, "now, 容器lst中的内容为:");  // -10 -20 -30 -40 -50 -60 -70 -80 -90

	transform(lst.begin(), lst.end(), std::ostream_iterator<int>(std::cout, " "), std::negate<int>()); // negate取负操作,将结果指定到输出流中输出,源区间lst容器中的值不变
	printContainer(lst, "\nnow, 容器lst中的内容为:");  // -10 -20 -30 -40 -50 -60 -70 -80 -90

	// ****************** transform(b1, e1, b2, b3, op) ******************
	printContainer(vt, "now, 容器vt中的内容为:");  // -1 -2 -3 -4 -5 -6 -7 -8 -9
	transform(vt.begin(), vt.end(), vt.begin(), vt.begin(), std::multiplies<int>()); //  将容器vt中数据自乘后放回到源容器;
	printContainer(vt, "now, 容器vt中的内容为:");  // 1 4 9 16 25 36 49 64 81
	transform(vt.begin(), vt.end(), vt.rbegin(), back_inserter(lst), std::plus<int>()); // 使用back_inserter方法, 相加后的结果插入到lst的后面,注意第三个参数为逆向迭代器
	printContainer(lst, "now, 容器lst中的内容为:");  // -10 -20 -30 -40 -50 -60 -70 -80 -90 82 68 58 52 50 52 58 68 82 
	transform(vt.begin(), vt.end(), lst.begin(), std::ostream_iterator<int>(std::cout, " "), std::minus<int>()); // 将vt中元素减去lst中元素的结果输出;vt和lst容器中的元素值无变化
	printContainer(vt, "now, 容器vt中的内容为:"); // 1 4 9 16 25 36 49 64 81
	printContainer(lst, "now, 容器lst中的内容为:"); // -10 -20 -30 -40 -50 -60 -70 -80 -90 82 68 58 52 50 52 58 68 82

	// ***** for_each 与 transform *****
	std::cout << "-----------------------------------\n";
	printContainer(vt, "now, 容器vt中的内容为:"); // 1 4 9 16 25 36 49 64 81
	for_each(vt.begin(), vt.end(), mySqrt);
	printContainer(vt, "now, 容器vt中的内容为:"); // 1 2 3 4 5 6 7 8 9
	transform(vt.begin(), vt.end(), vt.begin(), mySquare);  // 1 4 9 16 25 36 49 64 81
	printContainer(vt, "now, 容器vt中的内容为:");

	system("pause");
	return 0;
}
2.6 区间比较算法
算法解释
equal(b, e, b2);若b-e区间的值和b2开始的区间的值全相等,则为true,否则为false
equal(b, e, b2, p);
mismatch(b, e, b2);查找b-e区间的值和b2开始的区间的第一个不相等值,返回值为指向各自区间对应不相等的元素的迭代器;若 == container.end(), 说明这两个区间相等。
mismatch(b, e, b2, p);
lexicographical_compare(b, e, b2, e2);若b-e区间的元素值小于b2-e2区间的元素值,则为true,否则为false。区间比较大小的逻辑通字符串的比较。
lexicographical_compare(b, e, b2, e2, p);
#include<iostream>
#include<vector>
#include<list>
#include<algorithm>

using std::endl;
using std::cout;
using std::vector;

template <typename Container>
void printContainer(const Container& con, std::string str)
{
	std::cout << "-----------------------------------\n" << str.c_str();
	for (Container::const_iterator it = con.begin(); it != con.end(); ++it)
		std::cout << *it << " ";
	std::cout << "\n";
}

bool evenOrOdd(int elem1, int elem2)
{
	return elem1 % 2 == elem2 % 2;
}

bool myLess(std::list<int> lst1, std::list<int> lst2)
{
	return lexicographical_compare(lst1.begin(), lst1.end(), lst2.begin(), lst2.end());
}

void myPrint(std::list<int> lst)
{
	for (std::list<int>::iterator it = lst.begin(); it != lst.end(); ++it)
		cout << *it << " ";
	cout << endl;
}

int main()
{
	// ********** equal **********
	vector<int> vt = { 1,2,3,4,5,6,7,8,9 };
	vector<int> vt2(vt.rbegin(), vt.rend());  // 9 8 7 6 5 4 3 2 1
	printContainer(vt, "now, 容器vt中内容为:");
	printContainer(vt2, "now, 容器vt2中内容为:");
	if (equal(vt.begin(), vt.end(), vt2.rbegin()))  // if (equal(vt.rbegin(), vt.rend(), vt2.begin()))
		cout << "相等\n";  // equal比较,只有当比较的区间的所有元素全部相等时才为true

	if (equal(vt.begin(), vt.end(), vt2.rbegin(), evenOrOdd))
		cout << "奇偶顺序相同\n";

	reverse(vt2.begin(), vt2.end());
	vt2.push_back(0);
	printContainer(vt2, "now, 容器vt2中内容为:");  // 1 2 3 4 5 6 7 8 9 0
	if (!equal(vt.begin(), vt.end(), vt2.rbegin()))  // if (equal(vt.rbegin(), vt.rend(), vt2.begin()))
		cout << "不相等\n";  // equal比较,只有当比较的区间的所有元素全部相等时才为true
	
	// ********** mismatch ********** // 找两个容器中第一个不相等的元素的位置
	std::list<int> lst(vt2.begin(), vt2.end());
	std::pair<std::vector<int>::iterator, std::list<int>::iterator> pit;
	pit = mismatch(vt.begin(), vt.end(), lst.begin());
	if (pit.first == vt.begin())
		cout << "容器vt和lst中没有不匹配的数。\n"; // 但不能说明vt和lst相等
	vt[vt.size() / 2 + 1] = 0;
	printContainer(vt, "now, 容器vt中内容为:");   // 1 2 3 4 5 0 7 8 9
	printContainer(lst, "now, 容器lst中内容为:"); // 1 2 3 4 5 6 7 8 9 0
	pit = mismatch(vt.begin(), vt.end(), lst.begin());
	cout << "first mismatch: " << *pit.first << " " << *pit.second << endl;
	lst.pop_back(); 
	reverse(lst.begin(), lst.end());
	printContainer(lst, "now, 容器lst中内容为:");  // 9 8 7 6 5 4 3 2 1
	pit = mismatch(vt.begin(), vt.end(), lst.begin(), std::less_equal<int>()); // 找到vt容器中第一个大于lst的对应位置元素
	if(pit.first != vt.end())
		cout << "first greater: " << *pit.first << " " << *pit.second << endl;

	// ********** lexicographical_compare() ********** // 比较两个容器区间的大小,若第一个区间小于第二个区间,则返回true
	std::vector<std::list<int> > vlst = { {1,2,3,4,5}, {1,2,3,4,5,0}, {1,2,3,4,5, 2}, {1,2,3,4,5,2,0}, {1,2,3,4,5,7} };
	sort(vlst.begin(), vlst.end(), myLess);
	for_each(vlst.begin(), vlst.end(), myPrint);

	std::list<int> lst2 = {1,2,3,4,5}, lst3 = {1,2,3,4,5};
	cout << lexicographical_compare(lst2.begin(), lst2.end(), lst3.begin(), lst3.end()) << endl;  // 0

	//system("pause");
	return 0;
}
2.7 复制元素

copy()与copy_backward()
注意:
1. 没有copy_if()算法,可使用remove_copy_if()算法。
2. 复制过程中要逆序元素次序,可使用reverse_copy()算法。
3. 把容器内所有元素赋值给另一个元素,要使用赋值操作或容器的assign()成员函数
4. 复制过程中删除某些元素,使用remove_copy()和remove_copy_if()算法。
5. 复制中改变元素,使用transform()或replace_copy()算法。

#include<iostream>
#include<list>
#include<vector>
#include<algorithm>
#include<iterator>

using std::cout;
using std::endl;
using std::vector;
using std::list;

template <typename Container>
void printContainer(const Container& con, std::string str)
{
	std::cout << "-----------------------------------\n" << str.c_str();
	for (Container::const_iterator it = con.begin(); it != con.end(); ++it)
		std::cout << *it << " ";
	std::cout << "\n";
}

int main()
{
	// ********** copy ********** // copy时需要注意目标空间的大小要足够大
	vector<int> vt = { 1,2,3,4,5 };
	list<int> lst = { 0,1,2 };
	//copy(vt.begin(), vt.end(), lst.begin()); // 报错!目标容器的空间不够会报错
	copy(vt.begin(), vt.end(), back_inserter(lst)); //对于目标容器的空间不够,可以使用back_inserter方法
	printContainer(vt, "now, 容器vt中内容为:"); // 1 2 3 4 5
	printContainer(lst, "now, 容器lst中内容为:"); // 0 1 2 1 2 3 4 5
	vector<int> vt2(vt.size() * 4);
	printContainer(vt2, "now, 容器vt2中内容为:"); // 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
	copy(vt.begin(), vt.end(), vt2.begin()); // 结果:1 2 3 4 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
	copy(vt.begin(), vt.end(), vt2.begin()); // 只会copy到指定的位置 结果:1 2 3 4 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
	printContainer(vt2, "now, 容器vt2中内容为:"); // 1 2 3 4 5 0 0 0 0 0 0 0 0 0 0 1 2 3 4 5
	//copy(vt.begin(), vt.end(), vt2.end()); 报错
	copy(vt.begin(), vt.end(), vt2.begin() + vt.size());
	printContainer(vt2, "now, 容器vt2中内容为:"); // 1 2 3 4 5 1 2 3 4 5 0 0 0 0 0 0 0 0 0 0

	// ********** copy_backward ********** copy_backward 从后往前拷贝
	copy_backward(vt.begin(), vt.end(), vt2.end());
	printContainer(vt2, "now, 容器vt2中内容为:"); // 1 2 3 4 5 1 2 3 4 5 0 0 0 0 0 1 2 3 4 5
	copy(vt.rbegin(), vt.rend(), vt2.end() - vt.size()); // 使用逆序迭代器,反向拷贝
	printContainer(vt2, "now, 容器vt2中内容为:"); // 1 2 3 4 5 1 2 3 4 5 0 0 0 0 0 5 4 3 2 1
	reverse_copy(vt.begin(), vt.end(), vt2.end() - vt.size()); // ** 效果与上面使用逆向迭代器相同,反向copy
	printContainer(vt2, "now, 容器vt2中内容为:"); // 1 2 3 4 5 1 2 3 4 5 0 0 0 0 0 5 4 3 2 1
	reverse_copy(vt.rbegin(), vt.rend(), vt2.end() - vt.size()); //两次反向,相当于顺序copy
	printContainer(vt2, "now, 容器vt2中内容为:"); // 1 2 3 4 5 1 2 3 4 5 0 0 0 0 0 1 2 3 4 5
	

	copy(vt2.begin(), vt2.end(), std::ostream_iterator<int>(cout, " ")); // 将区间中元素copy到输出流,即输出;
	std::cout << std::endl;

	//system("pause");
	return 0;
}
2.8 交换算法

swap_range(b, e, b2);交换b到e区间的元素与b2开始的区间元素(交换相同个数)返回值为指向b2容器的第一个未交换的元素。
对于相同类型的容器,且交换两容器的所有元素(不管个数是否相同,全部交换),使用容器内部swap成员函数交换更快(实际交换容器内部的迭代器)

#include<iostream>
#include<vector>
#include<deque>
#include<algorithm>

using std::cout;
using std::endl;
using std::vector;
using std::deque;

template <typename Container>
void printContainer(const Container& con, std::string str)
{
	std::cout << "-----------------------------------\n" << str.c_str();
	for (Container::const_iterator it = con.begin(); it != con.end(); ++it)
		std::cout << *it << " ";
	std::cout << "\n";
}

int main()
{
	// ********** swap_ranges **********
	vector<int> vt = { 1,2,3,4,5 };
	deque<int> dq = { 9,8,7,6,5,4,3,2,1,0 };
	printContainer(vt, "now, 容器vt中内容为:"); // 1 2 3 4 5
	printContainer(dq, "now, 容器dq中内容为:"); // 10,9,8,7,6,5,4,3,2,1
	deque<int>::iterator pos = swap_ranges(vt.begin(), vt.end(), dq.begin());
	printContainer(vt, "after swap_ranges, 容器vt中内容为:"); // 10 9 8 7 6
	printContainer(dq, "after swap_ranges, 容器dq中内容为:"); // 1 2 3 4 5 5 4 3 2 1
	if (pos != dq.end())
		cout << "容器dq中第一个没有交换的数为:" << *pos << endl;
	swap_ranges(dq.begin(), dq.begin() + 4, dq.rbegin());
	printContainer(dq, "after self swap_ranges, 容器dq中内容为:"); // 0 1 2 3 5 4 4 3 2 1

	// ********** swap **********  // 对于相同类型的容器,交换所有元素,用swap成员函数更合适(交换内部指针,速度更快)
	vector<int> vt2(dq.begin(), dq.end());
	printContainer(vt, "now, 容器vt中内容为:"); // 9 8 7 6 5
	printContainer(vt2, "now, 容器vt2中内容为:"); // 0 1 2 3 5 4 4 3 2 1
	vt2.swap(vt);  // vt.swap(vt2);
	printContainer(vt, "after swap, 容器vt中内容为:"); // 0 1 2 3 5 4 4 3 2 1
	printContainer(vt2, "after swap, 容器vt2中内容为:"); // 9 8 7 6 5
	
	system("pause");
	return 0;
}
2.9 填充新值

fill(b, e, v)
fill(b, n, v)
generate(b, e, p)
generate_n(b, n, p)

#include<iostream>
#include<vector>
#include<list>
#include<string>
#include<algorithm>
#include<iterator>

using std::cout;
using std::endl;
using std::vector;
using std::string;
using std::list;

template <typename Container>
void printContainer(const Container& con, std::string str)
{
	std::cout << "-----------------------------------\n" << str.c_str();
	for (Container::const_iterator it = con.begin(); it != con.end(); ++it)
		std::cout << *it << " ";
	std::cout << "\n";
}

int main()
{
	// ********** fill & fill_n ********** // 填充新常量值
	vector<string> vts = { "hello " , "world ", "C++ ", "Welcome" };
	printContainer(vts, "now, 容器vts中的元素:");  // hello  world  C++  Welcome
	fill(vts.begin(), vts.end(), "Hello ");  
	printContainer(vts, "after fill, 容器vts中的元素:"); // Hello  Hello  Hello  Hello
	// fill_n(vts.begin(), 5, "World "); vts容器中只有4个元素,fill了5个,报错;fill_n函数需要目标容器有足够的容量来fill
	fill_n(back_inserter(vts), 5, "World "); // 使用back_inserter函数,直接在末尾插入,不需要提前分配内存。
	printContainer(vts, "after fill, 容器vts中的元素:");  // Hello  Hello  Hello  Hello  World  World  World  World  World
	list<string> lsts;
	fill_n(back_inserter(lsts), 10, "C++");  // C++ C++ C++ C++ C++ C++ C++ C++ C++ C++
	printContainer(lsts, "after fill_n, 容器lsts中的元素:");
	fill_n(lsts.begin(), lsts.size() - 4, "Primer");  // Primer Primer Primer Primer Primer Primer C++ C++ C++ C++
	printContainer(lsts, "after fill_n, 容器lsts中的元素:");
	fill_n(std::ostream_iterator<float>(cout, " "), 5, 12.3); cout << endl;  // 12.3 12.3 12.3 12.3 12.3 

	// ********** generate_n ********** // 填充新的可变值
	cout << "**************************************\n";
	list<int> lsti;
	generate_n(back_inserter(lsti), 5, rand);
	printContainer(lsti, "now, 容器lsti中内容为:");
	generate(lsti.begin(), lsti.end(), rand);
	printContainer(lsti, "now, 容器lsti中内容为:");

	//system("pause");
	return 0;
}
2.10 替换算法

replace(b, e, v1, v2); 将区间b-e的所有元素中的所有的值v1替换成v2
replace_if(b, e, op, v); 将区间b-e的所有元素中的所有满足op谓词的元素替换成v2
replace_copy(b1, e1, b2, v1, v2);
replace_copy_if(b1, e1, b2, p, v);

#include<iostream>
#include<list>
#include<algorithm>
#include<functional> // bind2nd 函数
#include<iterator>

using std::endl;
using std::cout;
using std::list;

template <typename Container>
void printContainer(const Container& con, std::string str)
{
	std::cout << "-----------------------------------\n" << str.c_str();
	for (Container::const_iterator it = con.begin(); it != con.end(); ++it)
		std::cout << *it << " ";
	std::cout << "\n";
}

int main()
{
	// ********** replace **********
	list<int> lst = { 1,3,5,7,1,2,3,4,5,6,6,6};
	printContainer(lst, "now, 容器lst中的元素:");  // 1,3,5,7,1,2,3,4,5,6,6,6
	replace(lst.begin(), lst.end(), 6, 9); // 将6全部替换成9
	printContainer(lst, "after replace, 容器lst中的元素:");  // 1,3,5,7,1,2,3,4,5,9,9,9
	replace_if(lst.begin(), lst.end(), std::bind2nd(std::less_equal<int>(), 3), 0); // 将小于等于3的数全部替换成0;
	printContainer(lst, "after replace_if, 容器lst中的元素:");  // 0 0 5 7 0 0 0 4 5 9 9 9

	// ********** replace_copy **********
	replace_copy(lst.begin(), lst.end(), std::ostream_iterator<int>(cout, " "), 5, 50);  // 0 0 50 7 0 0 0 4 50 9 9 9
	cout << endl; // 将5替换为50, replace_copy, 在replace之后再copy到输出流; 但lst中的元素无任何变化 
	replace_copy_if(lst.begin(), lst.end(), std::ostream_iterator<int>(cout, " "), std::bind2nd(std::modulus<int>(), 2), -1);
	cout << endl; // 上面操作将所有奇数替换成 -1, // 0 0 -1 -1 0 0 0 4 -1 -1 -1 -1
	printContainer(lst, "now, 容器lst中的元素:");  // 0 0 5 7 0 0 0 4 5 9 9 9 // replace_copy 以后,源容器中的元素值不变

	//system("pause");
	return 0;
}
2.11 删除算法

remove();
remove_if();
remove_copy();
remove_copy_if();
unique(); 删除连续重复的元素
unique_copy();
注意:remove()和remove_if()并不是真正的删除,而是把删除位置后面的元素赋值给前面的元素,容器中元素的个数并未减少。

#include<iostream>
#include<list>
#include<deque>
#include<algorithm>
#include<functional>
#include<iterator>

using std::endl;
using std::cout;
using std::list;

template <typename Container>
void printContainer(const Container& con, std::string str)
{
	std::cout << "-----------------------------------\n" << str.c_str();
	for (Container::const_iterator it = con.begin(); it != con.end(); ++it)
		std::cout << *it << " ";
	std::cout << "\n";
}

bool differenceOne(int elem1, int elem2)
{
	return abs(elem1 - elem2) == 1;
}

int main()
{
	// ************ remove 和 remove_if *************
	list<int> lst;
	for (int i = 0; i <= 5; ++i) {
		lst.push_front(i);
		lst.push_back(i);
	}
	printContainer(lst, "now, 容器lst中的内容为:");  // 5 4 3 2 1 0 0 1 2 3 4 5
	list<int>::iterator it = remove(lst.begin(), lst.end(), 3); // remove方法,将lst中3都删除,删除的位置有其后面的元素补上,返回值为逻辑终点
	printContainer(lst, "now, 容器lst中的内容为:");  // 5 4 2 1 0 0 1 2 4 5 4 5
	cout << "删除了" << distance(it, lst.end()) << "个3\n";
	lst.erase(it, lst.end());
	printContainer(lst, "now, 容器lst中的内容为:");  // 5 4 2 1 0 0 1 2 4 5
	lst.erase(remove_if(lst.begin(), lst.end(), std::bind2nd(std::greater<int>(), 3)), lst.end()); // 删除大于3的数
	printContainer(lst, "now, 容器lst中的内容为:");  // 2 1 0 0 1 2

	// ************ remove_copy 和 remove_copy_if *************
	std::deque<int> dq = {1,2,3,4,5,6,7,8,9,1,3,5,7,9};
	remove_copy(dq.begin(), dq.end(), std::ostream_iterator<int>(cout, " "), 1); // 删除1后,将剩余的数据送到输出流
	cout << endl; // 2 3 4 5 6 7 8 9 3 5 7 9
	remove_copy_if(dq.begin(), dq.end(), std::ostream_iterator<int>(cout, " "), std::bind2nd(std::less_equal<int>(), 3)); 
	cout << endl;   // 删除<=3的数后,将剩余的数据送到输出流 // 4 5 6 7 8 9 5 7 9  

	// ************ unique 和 unique_copy *************
	lst.push_back(2); lst.push_front(2);
	printContainer(lst, "now, 容器lst中的内容为:");  // 2 2 1 0 0 1 2 2
	it = unique(lst.begin(), lst.end());
	printContainer(lst, "now, 容器lst中的内容为:");  // 2 1 0 1 2 1 2 2
	for (list<int>::iterator iter = lst.begin(); iter != it; ++iter)
		cout << *iter << " ";
	cout << endl;  // 2 1 0 1 2
	lst.insert(lst.end(), dq.begin(), dq.end());
	printContainer(lst, "now, 容器lst中的内容为:");  // 2 1 0 1 2 1 2 2 1 2 3 4 5 6 7 8 9 1 3 5 7 9
	it = unique(lst.begin(), lst.end(), std::greater<int>()); // 若容器中该元素的值小于前一位置的元素值,则删除该元素
	printContainer(lst, "now, 容器lst中的内容为:");  // 2 2 2 2 2 3 4 5 6 7 8 9 9 6 7 8 9 1 3 5 7 9
	for (list<int>::iterator iter = lst.begin(); iter != it; ++iter)
		cout << *iter << " ";
	cout << endl;  // 2 2 2 2 2 3 4 5 6 7 8 9 9
	lst.push_back(9); lst.push_back(9);
	printContainer(lst, "now, 容器lst中的内容为:");  //  2 2 2 2 2 3 4 5 6 7 8 9 9 6 7 8 9 1 3 5 7 9
	unique_copy(lst.begin(), lst.end(), std::ostream_iterator<int>(cout, " "));// 2 3 4 5 6 7 8 9 6 7 8 9 1 3 5 7 9
	cout << endl;  // 将操作的结果送到输出流,源容器中的数据不变
	unique_copy(lst.begin(), lst.end(), std::ostream_iterator<int>(cout, " "), differenceOne); // 删除连续差值为1的数,注意,删除该元素后,其后的元素与之前的元素比较
	cout << endl;  // 2 2 2 2 2 4 6 8 6 8 1 3 5 7 9

	//system("pause");
	return 0;
}
2.12 逆转和旋转

reverse(b, e); 将b-e区间的元素逆转
reverse_copy();
rotate(b, be, e); 将[b,be) 和 [be, e)之间的元素旋转
rotate_copy();

#include<iostream>
#include<set>
#include<vector>
#include<algorithm>
#include<functional>
#include<iterator>

using std::endl;
using std::cout;
using std::set;
using std::vector;

template <typename Container>
void printContainer(const Container& con, std::string str)
{
	std::cout << "-----------------------------------\n" << str.c_str();
	for (Container::const_iterator it = con.begin(); it != con.end(); ++it)
		std::cout << *it << " ";
	std::cout << "\n";
}

int main()
{
	// ********** reverse **********
	vector<int> vt = { 1,2,3,4,5,6,7,8,9 };
	printContainer(vt, "now, 容器vt中的内容为;");  // 1,2,3,4,5,6,7,8,9
	reverse(++vt.begin(), --vt.end());
	printContainer(vt, "now, 容器vt中的内容为;");  // 1 8 7 6 5 4 3 2 9
	reverse_copy(vt.begin(), vt.end(), std::ostream_iterator<int>(cout, " "));
	cout << endl;  // 9 2 3 4 5 6 7 8 1

	// ********** rotate **********
	printContainer(vt, "now, 容器vt中的内容为;"); // 1 8 7 6 5 4 3 2 9
	rotate(vt.begin(), vt.begin() + vt.size() / 2, vt.end()); // rotate(it1, it2, it3),将区间[it1-it2)与[it2-it3)之间的元素互换
	printContainer(vt, "now, 容器vt中的内容为;"); // 5 4 3 2 9 1 8 7 6
	rotate(vt.begin(), find(vt.begin(),vt.end(), 9), vt.end());
	printContainer(vt, "now, 容器vt中的内容为;"); // 9 1 8 7 6 5 4 3 2

	// ********** rotate **********
	set<int> st(vt.begin(), vt.end());
	printContainer(st, "now, 容器st中的内容为;");  // 1,2,3,4,5,6,7,8,9
	set<int>::iterator it = st.end();
	advance(it, -(int)st.size() / 2); // 一般的随机迭代器可以直接:it = it - st.size() / 2; 但对于set的迭代器(为双向迭代器,内部为二叉树结构)中不能用这种方式,
	rotate_copy(st.begin(), it, st.end(), std::ostream_iterator<int>(cout, " ")); // rotate_copy 将旋转的结果copy到输出流
	cout << endl;
	printContainer(st, "now, 容器st中的内容为;");  // 1,2,3,4,5,6,7,8,9
	rotate_copy(st.begin(), find(st.begin(), st.end(), 5), st.end(), std::ostream_iterator<int>(cout, " ")); // rotate_copy 将旋转的结果copy到输出流
	cout << endl;

	//system("pause");
	return 0;
}
2.13 排列组合算法

next_permutation(); 从小到大排序输出下一个排列
prev_permutation(); 从大到小排序输出下一个排列

#include<iostream>
#include<vector>
#include<algorithm>

using std::endl;
using std::cout;
using std::vector;

int main()
{
	// ********** next_permutation **********
	vector<int> vt = {1,2,3,4};
	for (vector<int>::iterator it = vt.begin(); it != vt.end(); ++it)
		cout << *it << " ";
	cout << endl;
	while (next_permutation(vt.begin(), vt.end()))
	{
		for (vector<int>::iterator it = vt.begin(); it != vt.end(); ++it)
			cout << *it << " ";
		cout << endl;
	}
	cout << "-**************************-\n";
	vector<int> vt2 = { 1,4,3,2 };
	for (vector<int>::iterator it = vt2.begin(); it != vt2.end(); ++it)
		cout << *it << " ";
	cout << endl;
	while (next_permutation(vt2.begin(), vt2.end()))   // next_permutation, 从大到小排序
	{
		for (vector<int>::iterator it = vt2.begin(); it != vt2.end(); ++it)
			cout << *it << " ";
		cout << endl;
	}
	cout << "--------------------------\n";
	vt2 = { 1,4,3,2 };
	for (vector<int>::iterator it = vt2.begin(); it != vt2.end(); ++it)
		cout << *it << " ";
	cout << endl;
	while (prev_permutation(vt2.begin(), vt2.end()))   // next_permutation, 从小到大排序
	{
		for (vector<int>::iterator it = vt2.begin(); it != vt2.end(); ++it)
			cout << *it << " ";
		cout << endl;
	}
	
	//system("pause");
	return 0;
}
2.14 重排分区算法

random_shuffle(); 随机打乱容器中数据
partition(); 分区算法,将符合谓词的元素放在前面,不符合的放在后面。但该算法不稳定,原来分区后的符合谓词的数据顺序可能和分区前的顺序不一样。
stable_partition(); 稳定分区算法,原来分区后的符合谓词的数据顺序可能和分区前的顺序不一样。

#include<iostream>
#include<vector>
#include<algorithm>
#include<functional>

using std::endl;
using std::cout;
using std::vector;

template <typename Container>
void printContainer(const Container& con, std::string str)
{
	std::cout << "-----------------------------------\n" << str.c_str();
	for (Container::const_iterator it = con.begin(); it != con.end(); ++it)
		std::cout << *it << " ";
	std::cout << "\n";
}

bool modulus3(int elem)
{
	return !(elem % 3);
}

int main()
{
	// ********** random_shuffle **********
	vector<int> vt = {1,2,3,4,5,6,7,8,9};
	printContainer(vt, "now, 容器vt中的内容为;");  // 1,2,3,4,5,6,7,8,9
	random_shuffle(vt.begin(), vt.end());
	printContainer(vt, "now, 容器vt中的内容为;");  // 将容器中数据随机排列
	random_shuffle(vt.begin(), vt.end());
	printContainer(vt, "now, 容器vt中的内容为;"); 

	// ********** partition & stable_partition **********
	//partition(vt.begin(), vt.end(), modulus3);
	partition(vt.begin(), vt.end(), std::not1(std::bind2nd(std::modulus<int>(), 2))); //将偶数放在前面; 返回值为谓词逻辑的终点
	printContainer(vt, "now, 容器vt中的内容为;");  // 6 4 8 2 9 5 7 1 3  // 发现偶数不是按照之前的顺序排列的
	vt = { 1,2,3,4,5,6,7,8,9 };
	vector<int>::iterator it = stable_partition(vt.begin(), vt.end(), std::not1(std::bind2nd(std::modulus<int>(), 2))); //将偶数放在前面
	printContainer(vt, "now, 容器vt中的内容为;");  // 2 4 6 8 1 3 5 7 9  // 发现偶数不是按照之前的顺序排列的
	cout << "找到的偶数为:\n";
	for (vector<int>::iterator iter = vt.begin(); iter != it; ++iter)
		cout << *iter << " ";
	cout << endl;

	//system("pause");
	return 0;
}
2.15堆(heap)排序算法

将容器当做堆来处理
make_heap();
push_heap();
pop_heap();
sort_heap();
示例图,详情见下面代码

#include<iostream>
#include<vector>
#include<algorithm>
#include<functional>

using std::endl;
using std::cout;
using std::vector;

template <typename Container>
void printContainer(const Container& con, std::string str)
{
	std::cout << "-----------------------------------\n" << str.c_str();
	for (Container::const_iterator it = con.begin(); it != con.end(); ++it)
		std::cout << *it << " ";
	std::cout << "\n";
}

int main()
{
	// ********** make_heap **********
	vector<int> vt = {3,4,5,6,7,5,6,7,8,9,1,2,3,4}; //{1,2,3,3,4,4,5,5,6,6,7,7,8,9};
	//random_shuffle(vt.begin(), vt.end());
	printContainer(vt, "now, 容器vt中的内容为;");  // 3 4 5 6 7 5 6 7 8 9 1 2 3 4
	make_heap(vt.begin(), vt.end());
	printContainer(vt, "now, 容器vt中的内容为;");  // 9 8 6 7 7 5 5 3 6 4 1 2 3 4
	pop_heap(vt.begin(), vt.end());  // 取走最大数放在末尾,剩余的数仍然是一个堆的顺序
	printContainer(vt, "now, 容器vt中的内容为;");  // 8 7 6 7 4 5 5 3 6 4 1 2 3 9
	vt.pop_back(); // 删除最后的9
	printContainer(vt, "now, 容器vt中的内容为;");  // 8 7 6 7 4 5 5 3 6 4 1 2 3
	vt.push_back(10);  
	printContainer(vt, "now, 容器vt中的内容为;");  // 8 7 6 7 4 5 5 3 6 4 1 2 3 10
	push_heap(vt.begin(), vt.end()); // 重新生成新的堆
	printContainer(vt, "now, 容器vt中的内容为;");  // 10 7 8 7 4 5 6 3 6 4 1 2 3 5 
	sort_heap(vt.begin(), vt.end()); // 重新将按堆的排序重新排序
	printContainer(vt, "now, 容器vt中的内容为;");  // 1 2 3 3 4 4 5 5 6 6 7 7 8 10

	//system("pause");
	return 0;
}
2.16 排序算法

sort(b,e);
sort(b,e,op);
stable_sort(b,e);
stable_sort(b,e,op);
partial_sort(b, se, e);
partial_sort(b, se, e, op);
partial_sort_copy(sb, se, db, de);
partial_sort_copy(sb, se, db, de, op);
nth_element(b, n, e); 根据第n个元素排序
nth_element(b, n, e, op); // 与partition()类似,但partition()将满足要求的所有元素放在前面。而nth_element()只要满足要求的前n个数。
其中sort和stable_sort只能用于vevtor和deque容器,不能用于list容器(list容器有自己的内部的sort成员函数);stable_sort稳定排序。

#include<iostream>
#include<vector>
#include<algorithm>
#include<functional>
#include<iterator>

using std::endl;
using std::cout;
using std::vector;

template <typename Container>
void printContainer(const Container& con, std::string str)
{
	std::cout << "-----------------------------------\n" << str.c_str();
	for (Container::const_iterator it = con.begin(); it != con.end(); ++it)
		std::cout << *it << " ";
	std::cout << "\n";
}

int main()
{
	// ********** sort & stable_sort **********
	vector<int> vt = {1,3,5,7,9,8,6,4,2,9,6,3};
	printContainer(vt, "now, 容器vt中的内容为;");
	sort(vt.begin(), vt.end());  // stable_sort(vt.begin(), vt.end()); 默认从小到大排序,结果一样,但对于相同的元素,稳定排序保证之前相同的元素的顺序不变
	printContainer(vt, "now, 容器vt中的内容为;");  // 关于稳定排序,详情请自行百度
	vt = { 1,3,5,7,9,8,6,4,2,9,6,3 };
	sort(vt.begin(), vt.end(), std::greater<int>());  //从大到小排序
	printContainer(vt, "now, 容器vt中的内容为;"); // 9 9 8 7 6 6 5 4 3 3 2 1

	// ********** partial_sort **********
	vt = { 1,3,5,7,9,8,6,4,2,9,6,3 };
	printContainer(vt, "now, 容器vt中的内容为;"); // 1 3 5 7 9 8 6 4 2 9 6 3
	partial_sort(vt.begin(), vt.begin() + 6, vt.end()); //partial_sort(b, se, e); //相当于,找到前(se - b)个最小数
	printContainer(vt, "now, 容器vt中的内容为;"); // 1 2 3 3 4 5 9 8 7 9 6 6
	partial_sort(vt.begin(), vt.begin() + 6, vt.end(), std::greater<int>()); // 从大到小排序 
	printContainer(vt, "now, 容器vt中的内容为;"); // 9 9 8 7 6 6 1 2 3 3 4 5

	// ********** partial_sort_copy **********
	vector<int> vt2(4);
	vt = { 1,3,5,7,9,8,6,4,2,9,6,3 };
	partial_sort_copy(vt.begin(), vt.end(), vt2.begin(), vt2.end());
	printContainer(vt2, "now, 容器vt2中的内容为;"); // 1 2 3 3 // 容器vt2中只有4的容量,多余的装不下
	vt = { 1,3,5,7,9,8,6,4,2,9,6,3 };  // partial_sort_copy 返回值为逻辑终点
	vector<int>::iterator pos = partial_sort_copy(vt2.begin(), vt2.end(), vt.begin(), vt.end()); // 将容器vt2排序的结果copy到vt中(直接覆盖前面的vt2.size()个元素,vt后面的不变)
	printContainer(vt, "now, 容器vt中的内容为;"); // 1 2 3 3 9 8 6 4 2 9 6 3
	cout << "复制的内容为:";
	for (vector<int>::iterator iter = vt.begin(); iter != pos; ++iter)
		cout << *iter << " ";
	cout << endl;

	// ********** nth_element **********  ???? 次方法和一般的sort有何区别???
	nth_element(vt.begin(), vt.begin() + 3, vt.end(), std::greater<int>()); // 根据第n个数据排序
	printContainer(vt, "now, 容器vt中的内容为;"); // 9 9 8 6 6 4 3 3 3 2 2 1
	copy(vt.begin(), vt.begin() + 4, std::ostream_iterator<int>(cout, " "));

	//system("pause");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值