16.6 STL算法

16.6.4 函数和容器方法

STL方法更适用于特定的容器(非通用方法)。作为成员函数,它可以使用模板类的内存管理工具,从而在需要时调整容器的长度。

例如:

list<int la>

la.remove(4);//删除链表所有为4的元素,同时改变链表长度

last = remove(la.begin(),la.end(),4);//它将没被删除的元素放在链表的开始位置,并返回一个指向新超尾的迭代器。

la.erase(last,lb.end);//删除末尾元素

#include<iostream>
#include<list>
#include<algorithm>
const int LIM = 10;
void Show(int v)
{
	std::cout << v << " ";
}
int main()
{
	using namespace std;
	list<int> la = { 4,5,4,2,2,3,4,8,1,4 };
	list<int> lb(la);
	cout << "Original list contents:\n\t";
	for_each(la.begin(), la.end(), Show);
	cout << endl;
	la.remove(4);
	cout << "After using remove method:\n";
	cout << "la:\t";
	for_each(la.begin(), la.end(), Show);
	cout << endl;
	list<int>::iterator last;
	last = remove(lb.begin(), lb.end(), 4); //返回的是指向新超尾的迭代器
	cout << "After using the remove function:\n";
	cout << "lb:\t";
	for_each(lb.begin(), lb.end(), Show);
	cout << endl;
	lb.erase(last, lb.end());
	cout << "After using erase method:\n";
	cout << "lb:\t";
	for_each(lb.begin(), lb.end(), Show);
	cout << endl;
	system("pause");
	return 0;
}

16.6.5 使用STL

程序:用户输入单词,返回一个按字母排序的单词列表,并记录每个单词被输入的次数。

通过transform()完成字符串大小写转化。

string& ToLower(string& st)
{
transform(st.begin(),st.end(),tolower);
return st;
}
transform(words.begin(),words.end(),insert_iterator<<set>string>(wordset,wordset.begin()),ToLower);
//<<set>string>不加则缺少类模板类型,wrong

对于map,如果键无效,则对应值为0。

对于字符串函数参数参数传递,需要引用。

#include<iostream>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<iterator>
#include<algorithm>
#include<cctype>
using namespace std;

char toLower(char ch)
{
	return tolower(ch);
}
string& ToLower(string& st)
{
	transform(st.begin(), st.end(), st.begin(), tolower);
	return st;
}
void display(const string& s)
{
	cout << s << " ";
}
int main()
{
	vector<string> words;
	cout << "Enter words(enter quit to quit):\n";
	string input;
	while (cin >> input && input != "quit")
		words.push_back(input);
	cout << "You enter the following words:\n";
	for_each(words.begin(), words.end(), display);
	cout << endl;

	// place words in set, converting to lowercase
	set<string>wordset;
	transform(words.begin(), words.end(), insert_iterator<set<string>>(wordset, wordset.begin()), ToLower);
	cout << "\nAlphabetic list of words:\n";
	for_each(wordset.begin(), wordset.end(), display);
	cout << endl;

	//place word and frequency in map
	map<string, int> wordmap;
	set<string>::iterator si;
	for (si = wordset.begin();si != wordset.end();si++)
		wordmap[*si] = count(words.begin(), words.end(), *si);

	//display map contents
	cout << "\nWord frequency:\n";
	for (si = wordset.begin();si != wordset.end();si++)
		cout << *si <<": "<< wordmap[*si] << endl;
	system("pause");
	return 0;
}

16.7 其他库

C++提供了三个数组模板:vector,valarray,array.

扫描二维码关注公众号,回复: 11395916 查看本文章

vector是一个容器类和算法系统一部分,支持面向容器的操作,如排序,插入,搜索,转移到其它容器等。

valarray是面向数值计算的,支持数值计算。

array是替代内置数组而设计的,提供了多个STL方法,包括begin(),end(),rbegin(),rend()

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

int main()
{
	using namespace std;
	vector<double> data;
	double temp;

	cout << "Enter numbers (<=0 to quit):\n";
	while (cin >> temp && temp > 0)
		data.push_back(temp);
	sort(data.begin(), data.end());
	int size = data.size();
	valarray<double> numbers(size);
	int i;
	for (i = 0;i < size;i++)
		numbers[i] = data[i];
	valarray<double> sq_rts(size);
	sq_rts = sqrt(numbers);
	valarray<double> results(size);
	results = numbers + 2.0*sq_rts;
	cout.setf(ios_base::fixed);
	cout.precision(4);
	for (i = 0;i < size;i++)
	{
		cout.width(8);
		cout.setf(ios_base::left);
		cout << numbers[i] << ": ";
		cout.width(8);
		cout.unsetf(ios_base::left);
		cout << results[i] << endl;
	}
	cout << "done";
	system("pause");
	return 0;
}

Enter numbers (<=0 to quit):
3.3 4 5.5 6 7 8 2 -1
2.0000  :   4.8284
3.3000  :   6.9332
4.0000  :   8.0000
5.5000  :  10.1904
6.0000  :  10.8990
7.0000  :  12.2915
8.0000  :  13.6569
done请按任意键继续. . .

vector 和 valarray的对比:

注意functional库内嵌bind1st和bind2nd分别表示将常数赋给第一个参数和第二个参数。

#include<iostream>
#include<vector>
#include<array>
#include<valarray>
#include<functional>
using namespace std;
double COS(double x)
{
	return cos(x);
}
int main()
{
	vector<double> ved1(10), ved2(10), ved3(10);
	array<double, 3> vod1,vod2,vod3;
	valarray<double>vad1(10), vad2(10), vad3(10);
	vad3 = 10.0*((vad1 + vad2) / 2.0 + vad1*cos(vad2));
	cout << vad3.size()<<" "<<vad3[0] << endl;//size=10,content=0
	transform(ved2.begin(), ved2.end(), ved3.begin(), COS);
	transform(ved1.begin(), ved1.end(), ved3.begin(), ved3.begin(), multiplies<double>());
	transform(ved1.begin(), ved1.end(), ved2.begin(), ved1.begin(), plus<double>());
	//位于functional库中
	transform(ved1.begin(), ved1.end(), ved1.begin(), bind2nd(divides<double>(), 2.0));
	transform(ved1.begin(), ved1.end(), ved3.begin(), ved3.begin(), plus<double>());
	transform(ved3.begin(), ved3.end(), ved3.begin(), bind1st(multiplies<double>(), 10.0));
	cout << vad3.size() << " " << vad3[0] << endl;//size=10,content=0
	system("pause");
	return 0;
}

slice切片:

slice对象被初始化为三个整数值,分别为起始索引、索引数、跨距,与python类似。

#include<iostream>
#include<valarray>
#include<cstdlib>
#include<vector>
using namespace std;

const int SIZE = 12;
typedef std::valarray<int> vint;//predefined
void show(const vint& v, int cols)
{
	int lim = v.size();
	//cout << size(v) << endl;
	for (int i = 0;i < lim;i++)
	{
		cout.width(3);
		cout << v[i];
		if (i%cols == cols - 1)
			cout << endl;
		else
			cout << ' ';
	}
	if (lim%cols != 0)
		cout << endl;
}
int main()
{
	vint valint(SIZE);
	int i;
	for (i = 0;i < SIZE;i++)
		valint[i] = rand() % 10;
	cout << "Original array:\n";
	show(valint, 3);
	vint vcol(valint[slice(1, 4, 3)]);
	cout << "second column:\n";
	show(vcol, 1);
	vint vrow(valint[slice(3, 3, 1)]);
	cout << "second row:\n";
	show(vrow, 3);
	valint[slice(2, 4, 3)] = 10;
	cout << "new assigned" << endl;
	show(valint, 3);
	cout << "common:\n";
	valint[slice(0, 4, 3)] = vint(valint[slice(1, 4, 3)]) + vint(valint[slice(2, 4, 3)]);
	//wrong for valint[slice(1,4,3)]并没有定义运算符+。因此程序使用slice指定的元素创建一个完整的vint对象,以便能够加法运算
	//valint[slice(0, 4, 3)] = valint[slice(1, 4, 3)] + valint[slice(2, 4, 3)];
	show(valint, 3);
	
	system("pause");
	return 0;
}

Original array:
  1   7   4
  0   9   4
  8   8   2
  4   5   5
second column:
  7
  9
  8
  5
second row:
  0   9   4
new assigned
  1   7  10
  0   9  10
  8   8  10
  4   5  10
common:
 17   7  10
 19   9  10
 18   8  10
 15   5  10
请按任意键继续. . .

模板initializer_list

initializer_list类的初衷旨在让您能够将一系列值传递给构造函数或其他函数。

std::vector<int> values = {10,8,5.5};会报错,不允许窄带转换

std::vector<double> values = {10,5.5};但是这样可以 

#include<iostream>
#include<initializer_list>
using namespace std;

double sum(initializer_list<double> il)
{
	double tot = 0;
	for (auto p = il.begin();p != il.end();p++)
		tot += *p;
	return tot;
}
double average(const initializer_list<double>& ril)
{
	double tot = 0;
	int n = ril.size();
	double ave = 0.0;
	if (n > 0)
	{
		for (auto p = ril.begin();p != ril.end();p++)
			tot += *p;
		ave = tot / n;
	}
	return ave;
}
int main()
{
	cout << "List 1: sum= " << sum({ 2,3,4 }) << ", ave= " << average({ 2,3,4 }) << endl;
	initializer_list<double> dl = { 1.1,2.2,3.3,4.4,5.5 };
	cout << "List 2: sum= " << sum(dl) << ", ave= " << average(dl) << endl;
	dl = { 19.0,2.1,33.4,5.9 };
	cout << "List 3: sum= " << sum(dl) << ", ave= " << average(dl) << endl;
	system("pause");
	return 0;
}

List 1: sum= 9, ave= 3
List 2: sum= 16.5, ave= 3.3
List 3: sum= 60.4, ave= 15.1
请按任意键继续. . .

猜你喜欢

转载自blog.csdn.net/qq_40801709/article/details/106296387