# 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

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


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

char toLower(char 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.

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的对比：

#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;
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;
}
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

06-26 8

09-11 9215

06-21 1057

11-14 14

05-02 106

09-23 1656

05-02 12

04-17 38

04-13 172

03-19 80万+

04-14 56万+

02-19 16万+

02-27 7万+

02-28 4万+

03-01 12万+

03-01 11万+

03-03 6066

03-04 12万+

03-05 9638

03-05 5万+

03-08 6万+

03-08 1万+

04-25 6万+

03-10 12万+

03-10 17万+

03-10 6277

03-12 10万+

03-13 10万+

03-16 9939

03-19 7万+

03-20 4913

03-23 1万+

03-24 3万+

03-25 2万+

03-25 8万+

03-27 1万+

03-29 20万+

03-29 9万+

03-30 14万+

05-21 2846

03-31 1万+

03-23 1万+

04-02 3万+

05-06 2万+

04-05 1万+

04-06 6万+

04-09 1万+

04-09 7万+

04-09 4642

04-10 4178

04-11 2万+

04-15 5万+

04-18 1万+

04-18 3726

04-18 4万+

04-20 3万+

04-24 2万+

04-26 3365

04-24 3960

04-30 7147

05-16 4万+

05-08 3万+

05-10 1815

05-11 3万+

05-13 6693

05-19 5610

05-13 9689

05-14 3604

05-14 6070

05-16 1892

05-16 1291

05-16 9302

05-16 1万+

05-17 4184

05-17 2318

05-18 1121

05-18 6071

05-19 5934

05-20 3391

#### 两个字符串问题给我整懵了，面试官：“你对我们公司还有什么想问的？”

©️2019 CSDN 皮肤主题: 技术工厂 设计师: CSDN官方博客