第 10 章 泛型算法

练习 10.1 && 练习 10.2

#include
#include
#include
#include
using namespace std;

int main()
{
	vector iv = { 3,2,3,4,3,5 };
	cout << count(iv.begin(), iv.end(), 3) << endl;

	list lst = { "hello", "C++", "hello", "Python" };
	cout << count(lst.begin(), lst.end(), "hello") << endl;

	return 0;
}

练习 10.3:

#include
using namespace std;
#include
#include
#include

int main()
{
	vector v = { 1,2,3,4,5 };
	int sum = accumulate(v.begin(), v.end(), 0);
	cout << sum << endl;

	return 0;
}

练习 10.4:

#include
using namespace std;
#include
#include
#include

// accumulate的第三个参数是和的初始值,它还决定了函数的返回类型,以及函数中使用哪个加法运算符。 
// 第三个参数为0则使用整型加法运算符。正确的调用方法是将0.0作为第三个参数传递给accumulate.
int main()
{
	vector v2 = { 1.1,2.2,3.3};
    double sum1 = accumulate(v2.begin(), v2.end(), 0);    // sum1 = 6
	double sum2 = accumulate(v2.begin(), v2.end(), 0.0);  // sum2 = 6.6
	cout << sum1 << " " << sum2 << endl;

	return 0;
}

练习 10.5:

#include
#include
#include
#include
using namespace std;

int main()
{
	vector roster1{ "Hello Cpp" };
	vector roster2{ "Hello Cpp" };
	bool ret = equal(roster1.begin(), roster1.end(), roster2.begin());    // 正常调用

	cout << ret << endl;

	return 0;
}

练习 10.6:

#include
#include
#include
using namespace std;

int main()
{
	vector iv = { 0,1,2,3,4,5,6,7,8,9 };
	fill_n(iv.begin(), iv.size(), 0);
	for (auto i : iv)
		cout << i << " ";
	cout << endl;

	return 0;
}

练习 10.7:

#include
#include
#include
#include
using namespace std;

int main()
{
	// a
	vector vec; list lst; int i;
	while (cin >> i)
		lst.push_back(i);
    // copy算法要求目标序列至少要包含与源序列一样多的元素
	// copy(lst.cbegin(), lst.cend(), vec.begin());	
	copy(lst.cbegin(), lst.cend(), back_inserter(vec));

	// b
	vector v;
	v.reserve(10);	//	reserve申请容量,v的size为空
	//fill_n(v.begin(), 10, 0);	// v仍然为空,fill_n算法不具备向容器添加元素的能力
	fill_n(back_inserter(v), 10, 0);

	for (auto c : v)
		cout << c << " ";
	cout << endl;

	return 0;
}

练习 10.8:

        back_inserter是一种向容器种添加元素的迭代器迭代器,当一个算法操作一个这样的迭代器时,迭代器可以完成向容器添加元素的效果,但是标准库算法本身不直接操作容器,它们只操作迭代器,从而间接访问容器。

练习 10.9:

#include
#include
#include
#include
using namespace std;

void elimDips(vector& words)
{
	// 按字典排序words,以便查找重复单词
	sort(words.begin(), words.end());
	// unique重排输入范围,使得每个单词只出现一次
	// 排列在范围的前部,返回指向不重复区域之后一个位置的迭代器
	auto unique_end = unique(words.begin(), words.end());
	// 删除重复单词
	words.erase(unique_end, words.end());
}

int main()
{
	vector words{ "the", "quick","red","fox","jumps",
		"over","the","slow","red","turtle" };
	elimDips(words);
	for (const auto& word : words)
		cout << word << " ";
	cout << endl;
	
	return 0;
}

练习 10.10:

标准库算法对迭代器而不是容器进行操作。因此,算法不改变容器大小。

练习 10.11:

#include
#include
#include
#include
using namespace std;

void elimDips(vector& words)
{
	sort(words.begin(), words.end());
	auto unique_end = unique(words.begin(), words.end());
	words.erase(unique_end, words.end());
}

bool isShorter(const string& s1, const string& s2)
{
	return s1.size() < s2.size();
}

int main()
{
	vector words{ "the", "quick","red","fox","jumps",
		"over","the","slow","red","turtle" };
	elimDips(words);

	stable_sort(words.begin(), words.end(), isShorter);
	for (const auto& word : words)
		cout << word << " ";	// fox red the over slow jumps quick turtle
	cout << endl;

	return 0;
}

练习 10.12:

#include
#include
#include
#include
using namespace std;

// 声明read函数
struct Sales_data;
istream& read(istream& is, Sales_data& item);

class Sales_data
{
	friend Sales_data add(const Sales_data& lhs, const Sales_data& rhs);
	friend istream& read(istream& is, Sales_data& item);
	friend ostream& print(ostream& os, const Sales_data& item);
public:
	// 构造函数
	Sales_data() = default;
	Sales_data(const string& s) :bookNo(s) {}
	Sales_data(const string& s, unsigned n, double p) :bookNo(s), units_sold(n), revenue(n* p) {}
	Sales_data(istream& is)
	{
		read(is, *this);
	}
	// 成员函数
	string isbn() const;
	const Sales_data& combine(const Sales_data& rhs);

private:
	inline double avg_price()const;

private:
	// 成员属性
	string bookNo;
	unsigned units_sold = 0;
	double revenue = 0.0;
};

inline double Sales_data::avg_price()const
{
	return units_sold ? revenue / units_sold : 0;
}

string Sales_data::isbn()const
{
	return this->bookNo;
}

const Sales_data& Sales_data::combine(const Sales_data& rhs)
{
	this->units_sold += rhs.units_sold;
	this->revenue += rhs.revenue;
	return *this;
}

Sales_data add(const Sales_data& lhs, const Sales_data& rhs)
{
	Sales_data sum = lhs;
	sum.combine(rhs);
	return sum;
}

istream& read(istream& is, Sales_data& item)
{
	double price = 0;
	is >> item.bookNo >> item.units_sold >> price;
	item.revenue = item.units_sold * price;
	return is;
}

ostream& print(ostream& os, const Sales_data& item)
{
	os << item.bookNo << " " << item.units_sold << " " << item.revenue;
	return os;
}

bool compareIsbn(const Sales_data& lhs, const Sales_data& rhs)
{
	return lhs.isbn() < rhs.isbn();
}

int main()
{
	Sales_data d1("0 - 201 - 70353 - X", 4, 25.0), d2("0 - 201 - 82470 - 1", 4, 30.0),
		d3("0 - 399 - 82477 - 1", 2, 15.00), d4("0 - 201 - 88954 - 4", 5, 12.00);
	vector vec{ d1, d2, d3, d4 };
	sort(vec.begin(), vec.end(), compareIsbn);
	
	for (const auto& elem : vec)
		print(cout, elem) << endl;

	return 0;
}

练习 10.13:

#include
#include
#include
#include
using namespace std;

bool LengthGreaterFive(const string& s)
{
	return s.size() > 5;
}

int main()
{
	vector words{ "Cpp", "Java", "Python", "Golang" };
	auto part = partition(words.begin(), words.end(), LengthGreaterFive);
	
	for (auto iter = words.cbegin(); iter != part; ++iter)
		cout << *iter << " ";
	cout << endl;

	return 0;
}

练习 10.14:

#include
using namespace std;

int main()
{
	auto sum = [](int a, int b) {return a + b; };
	cout << sum(1,1) << endl;

	return 0;
}

练习 10.15:

#include
using namespace std;

int main()
{
	int a = 6;
	auto sum = [a](int b) {return a + b; };
	cout << sum(3) << endl;

	return 0;
}

练习 10.16:

#include
#include
#include
#include
using namespace std;

void elimDips(vector& words)
{
	sort(words.begin(), words.end());
	auto unique_end = unique(words.begin(), words.end());
	words.erase(unique_end, words.end());
}

void biggies(vector& words, vector::size_type sz)
{
	elimDips(words);	// 按字典排序,删除重复单词
	// 按长度排序,长度相同的单词维持字典排序
	stable_sort(words.begin(), words.end(), [](const string& lhs, const string& rhs) 
		{return lhs.size() < rhs.size(); });
	// 获取一个迭代器指向第一个满足s.size() >= sz的元素
	auto wc = find_if(words.begin(), words.end(), [sz](const string& s) 
		{return s.size() >= sz; });
	// 输出满足s.size() >= sz的元素
	for_each(wc, words.end(), [](const string& s) {cout << s << " "; });
	cout << endl;
}

int main()
{
	vector words{ "the", "quick","red","fox","jumps",
		"over","the","slow","red","turtle" };
	biggies(words, 5);

	return 0;
}

练习 10.17:

#include
#include
#include"Sales_data.h"

int main()
{
	Sales_data d1("0 - 201 - 70353 - X", 4, 25.0), d2("0 - 201 - 82470 - 1", 4, 30.0),
		d3("0 - 399 - 82477 - 1", 2, 15.00), d4("0 - 201 - 88954 - 4", 5, 12.00);
	vector vec{ d1, d2, d3, d4 };
	sort(vec.begin(), vec.end(), [](const Sales_data& sd1, const Sales_data& sd2)
		{return sd1.isbn() < sd2.isbn();});

	for (const auto& elem : vec)
		print(cout, elem) << endl;

	return 0;
}

练习 10.18 && 练习 10.19:

#include
#include
#include
#include
using namespace std;

void elimDips(vector& words)
{
	sort(words.begin(), words.end());
	auto unique_end = unique(words.begin(), words.end());
	words.erase(unique_end, words.end());
}
// 10.18
void biggies_partition(vector& words, vector::size_type sz)
{
	elimDips(words);	// 按字典排序,删除重复单词
	// 按长度排序,长度相同的单词维持字典排序
	stable_sort(words.begin(), words.end(), [](const string& lhs, const string& rhs)
		{return lhs.size() < rhs.size(); });
	// 获取一个迭代器指向满足s.size() >= sz的元素之后的位置
	auto partition_end = partition(words.begin(), words.end(), [sz](const string& s)
		{return s.size() >= sz; });
	// 输出满足s.size() >= sz的元素
	for_each(words.begin(), partition_end, [](const string& s) {cout << s << " "; });
	cout << endl;
}
// 10.19
void biggies_stable_partition(vector& words, vector::size_type sz)
{
	elimDips(words);	// 按字典排序,删除重复单词
	// 按长度排序,长度相同的单词维持字典排序
	stable_sort(words.begin(), words.end(), [](const string& lhs, const string& rhs)
		{return lhs.size() < rhs.size(); });
	// 获取一个迭代器指向满足s.size() >= sz的元素之后的位置
	auto partition_end = stable_partition(words.begin(), words.end(), [sz](const string& s)
		{return s.size() >= sz; });
	// 输出满足s.size() >= sz的元素
	for_each(words.begin(), partition_end, [](const string& s) {cout << s << " "; });
	cout << endl;
}

int main()
{
	vector words{ "the", "quick","red","fox","jumps",
		"over","the","slow","red","turtle" };
	biggies_partition(words, 5);
	biggies_stable_partition(words, 5);

	return 0;
}

练习 10.20:

#include
#include
#include
#include
using namespace std;

int main()
{
	vector words{ "Cpppremer", "Java","Python","Golang" };
	auto count = count_if(words.begin(), words.end(), 
		[](const string& s) {return s.size() > 6; });
	cout << count << endl;
	return 0;
}

练习 10.21:

#include
#include
#include
#include
using namespace std;

int main()
{
	int i = 6;
	auto f = [&i]()->bool
	{
		if (i)
		{
			--i;
			return false;
		}
		else
			return true;
	};
	while(!f())
		cout << i << endl;
	return 0;
}

练习 10.22:

#include
#include
#include
#include
#include
using namespace std;
using namespace placeholders;

bool lessThanOrEqualTo(const string& s, string::size_type sz)
{
	return s.size() <= sz;
}


int main()
{
	vector words{ "Cpppremer", "Java","Python","Golang" };
	auto count = count_if(words.begin(), words.end(),
		bind(lessThanOrEqualTo, _1, 6));
	cout << count << endl;

	return 0;
}

练习 10.23:

        bind接受的参数为绑定的函数以及对应函数的参数;当使用bind生成一个可调用对象时,该对象的参数取决于bind中有几个占位符;

练习 10.24:

#include
#include
#include
#include
#include
using namespace std;
using namespace placeholders;

bool check_size(const string& s, string::size_type sz)
{
	return s.size() < sz;
}

int main()
{
	vector iv{ 0,1,2,3,4,5,6,7,8,9 };
	string s("cpp");
	auto ret = find_if(iv.begin(), iv.end(), bind(check_size, s, _1));
	cout << *ret << endl;

	return 0;
}

练习 10.25:

#include
#include
#include
#include
#include
using namespace std;
using namespace placeholders;

void elimDips(vector& words)
{
	sort(words.begin(), words.end());
	auto unique_end = unique(words.begin(), words.end());
	words.erase(unique_end, words.end());
}

bool check_size(const string& s, string::size_type sz)
{
	return s.size() >= sz;
}

void biggies_stable_partition(vector& words, vector::size_type sz)
{
	elimDips(words);
	stable_sort(words.begin(), words.end(), [](const string& lhs, const string& rhs)
		{return lhs.size() < rhs.size(); });
	auto partition_end = stable_partition(words.begin(), words.end(), 
		bind(check_size, _1, sz));
	for_each(words.begin(), partition_end, [](const string& s) {cout << s << " "; });
	cout << endl;
}

int main()
{
	vector words{ "the", "quick","red","fox","jumps",
		"over","the","slow","red","turtle" };
	biggies_stable_partition(words, 5);

	return 0;
}

练习 10.26:

        back_inserter创建一个使用push_back的迭代器,front_inserter创建一个使用push_front的迭代器,inserter创建一个使用inserter的迭代器。back_inserter总是插入到容器尾元素之,front_inserter 总是插入到元素首元素之前,而inserter则是插入到给定位置之前。

练习 10.27:

#include
#include
#include
#include
#include
using namespace std;

int main()
{
	vector iv{ 0,4,1,3,2,1,3,2 };
	list lst;
	sort(iv.begin(), iv.end());
	unique_copy(iv.begin(), iv.end(), back_inserter(lst));
	for (const auto& i : lst)
		cout << i << " ";
	cout << endl;

	return 0;
}

练习 10.28:

#include
#include
#include
#include
#include
using namespace std;

void print(const list& lst)
{
	for (const auto& i : lst)
		cout << i << " ";
	cout << endl;
}

int main()
{
	vector iv{ 1,2,3,4,5,6,7,8,9 };

	list l1;
	copy(iv.begin(), iv.end(), inserter(l1, l1.begin()));
	print(l1);
	
	list l2;
	copy(iv.begin(), iv.end(), back_inserter(l2));
	print(l2);

	list l3;
	copy(iv.begin(), iv.end(), front_inserter(l3));
	print(l3);

	return 0;
}

练习 10.29:

#include
#include
#include
#include
using namespace std;

int main()
{
	ifstream ifs("words.txt");
	istream_iterator in(ifs), eof;
	vector vec(in, eof);
	// 输出
	copy(vec.begin(), vec.end(), ostream_iterator(cout, "\n"));

	return 0;
}

练习 10.30:

#include
#include
#include
#include
using namespace std;

int main()
{
	istream_iterator in(cin), eof;
	vector vec(in, eof);
	sort(vec.begin(), vec.end());
	copy(vec.begin(), vec.end(), ostream_iterator(cout, " "));
	cout << endl;

	return 0;
}

练习 10.31:

#include
#include
#include
#include
using namespace std;

int main()
{
	istream_iterator in(cin), eof;
	vector vec(in, eof);
	sort(vec.begin(), vec.end());
	unique_copy(vec.begin(), vec.end(), ostream_iterator(cout, " "));
	cout << endl;

	return 0;
}

练习 10.32:

#include
#include
#include
#include
#include"Sales_item.h"
using namespace std;

int main()
{
	istream_iterator in(cin), eof;
	vector vec(in, eof);	// 保存交易记录
	sort(vec.begin(), vec.end(), [](const Sales_item& lhs, const Sales_item& rhs)
		{return lhs.isbn() < rhs.isbn(); });
	for (auto beg = vec.begin(), end = beg; beg != vec.end(); beg = end)
	{
		end = find_if(beg, vec.end(), [beg](const Sales_item& item)
			{return item.isbn() != beg->isbn(); });
		auto total = accumulate(beg, end, Sales_item(beg->isbn()));
		cout << total << endl;
	}

	return 0;
}

练习 10.33:

#include
#include
#include
#include
#include
using namespace std;

void fstream_in_out(ifstream& ifs, ofstream& ofs_odd, ofstream& ofs_even)
{
	istream_iterator in(ifs), eof;
	ostream_iterator out_odd(ofs_odd, " "), out_even(ofs_even, "\n");
	while (in != eof)
		*(*in % 2 ? out_odd : out_even)++ = *in++;
	// 使用for_each
	/*for_each(in, eof, [&out_odd, &out_even](const int i) 
		{*(i % 2 ? out_odd : out_even)++ = i; });*/
}

int main()
{
	ifstream ifs("in.txt");
	ofstream ofs_odd("odd.txt"), ofs_even("even.txt");
	fstream_in_out(ifs, ofs_odd, ofs_even);

	return 0;
}

练习 10.34:

#include
#include
#include
using namespace std;

int main()
{
	vector vec{ 0,1,2,3,4,5,6,7,8,9 };
	for_each(vec.crbegin(), vec.crend(), [](int i) {cout << i << " "; });
	cout << endl;

	return 0;
}

练习 10.35:

#include
#include
using namespace std;

int main()
{
	vector vec{ 0,1,2,3,4,5,6,7,8,9 };
	for (auto iter = vec.cend(); iter != vec.cbegin();)
		cout << *(--iter) << " ";
	cout << endl;

	return 0;
}

练习 10.36:

#include
#include
#include
using namespace std;

int main()
{
	list lst{ 6,0,2,3,0,5,0,7,8,9 };
	auto zero_end = find(lst.crbegin(), lst.crend(), 0);
	cout << "the last of " << *zero_end << " in front of " << *zero_end.base() << endl;

	return 0;
}

练习 10.37:

#include
#include
#include
#include
using namespace std;

int main()
{
	vector vec{ 0,1,2,3,4,5,6,7,8,9 };
	list lst(7 - 3 + 1);
	copy(vec.begin() + 3, vec.begin() + 8, lst.rbegin());
	for_each(lst.begin(), lst.end(), [](int i) {cout << i << " "; });
	cout << endl;

	return 0;
}

练习 10.38:

  • 输入迭代器:只读,不写;单遍扫描,只能递增,支持相等性判定运算符(==、!=)、解引用运算符(*)和箭头运算符(->)。
  • 输出迭代器:只写,不读;单遍扫描,只能递增,支持解引用运算符(*)。
  • 前向迭代器:可读写;多遍扫描,只能递增,支持所有输入、输出迭代器的操作。
  • 双向迭代器:可读写;多遍扫描,可递增递减,支持所有前向迭代器操作,还支持前置和后置递减运算符(--)。
  • 随机访问迭代器:可读写,多遍扫描,支持全部迭代器运算。

练习 10.39:

list上的迭代器是双向迭代器,vector上的迭代器是随机访问迭代器。

练习 10.40:

  • copy要求前两个参数至少是输入迭代器,表示一个输入范围。它读取这个范围中的元素,写入到第三个参数表示的输出序列中,因此第三个参数至少是输出迭代器。
  • reverse要反向处理序列,因此它要求至少是双向迭代器。
  • unique顺序扫描元素,移除重复的元素,因此要求两个参数至少是前向迭代器。

练习 10.41:

// 将范围[beg, end)中的old_val替换为new_val
replace(beg, end, old_val, new_val);
// 将范围[beg, end)中谓词pred为真的元素替换为new_val
replace_if(beg, end, pred, new_val);
// 将范围[beg, end)中的old_val替换为new_val,并把元素拷贝到目的序列dest
replace_copy(beg, end, dest, old_val, new_val);
// 将范围[beg, end)中谓词pred为真的元素替换为new_val,并把元素拷贝到目的序列dest
replace_copy_if(beg, end, dest, pred, new_val);

练习 10.42:

#include
#include
#include
#include
using namespace std;

void elimDips(list& words)
{
	words.sort();
	words.unique();
}

int main()
{
	list words{ "the", "quick","red","fox","jumps",
		"over","the","slow","red","turtle" };
	elimDips(words);
	for_each(words.begin(), words.end(), [](const string& s) {cout << s << " "; });
	cout << endl;

	return 0;
}

你可能感兴趣的:(C++,Primer,第5版,学习笔记,c++)