您的位置:首页 > 编程语言 > C语言/C++

STL之常用算法(C++)持续更新

2019-03-18 18:53 120 查看

STL之常用算法

概述

  1. STL将算法和容器分开,使得更容易加入新算法。这样实现的STL能更加有效,避免了虚函数调用的相关开销。
  2. STL算法不依赖于所操作容器的实现细节。只要容器(或数组)的迭代器符合算法要求,STL算法即可像STL容器一样处理任何C语言式、基于指针的数组(以及用户自定义的数据结构)。
  3. 不必修改容器就能方便地将算法加进STL中。

0. 头文件

#include<algorithm>

1.fill、fill_n、generate、generate_n

  • 函数fill和fill_n将容器中一定范围的元素设置为特定值。
  • 函数generate和generate_n用产生器函数生成容器中一定范围的元素值。产生器函数不取参数,并返回可以放在容器元素中的值。
vector<char>v1(10); //输出v1:0 0 0 0 0 0 0 0 0 0

//将字符‘5’放在v1从begin到end(不包括end)的每个元素中
fill(v1.begin(), v1.end(), '5');  //输出v1:5 5 5 5 5 5 5 5 5 5

//将字符‘A’放在v1的前5个元素中
fill_n(v1.begin(), 5, 'A'); //输出v1:A A A A A 5 5 5 5 5

//将调用产生器函数nextLetter得到的结果放在v1的begin到end(不包括end)的每个元素中
generate(v1.begin, v1.end(), nextLetter); //输出v1:A B C D E F G H I J

//将调用产生器函数nextLetter得到的结果放在v1的前5个元素中
generate_n(v1.begin(), 5, nextLetter); //输出v1:K L M N O F G H I J

char nextLetter() {
static char letter = 'A';
return letter++;
}

2. equal、mismatch、lexicographical_compare

  • 函数equal比较两个数值序列的相等性,每个序列不一定包含相同的元素个数,如果两个序列的元素个数不同,则equal返回false。函数operator==进行元素的比较。
  • 函数equal有一种形式:取一个二元判定函数作为第4个参数,二元判定函数接受两个要比较的元素并返回一个bool值,表示元素是否相同。这可以在存放数值指针而不是存放实际数值的序列中有用,因为可以定义指针所指项目的比较,而不是比较指针内容(即指针中存放的地址)。
  • 函数mismatch比较两个数值序列,返回一个pair迭代器对,表示每个序列中不匹配元素的地址。如果所有元素匹配,则pair中的两个迭代器等于每个序列的end()。同函数equal一样,mismatch也有另一种形式:取一个二元判定函数作为第4个参数。
  • 函数lexicographical比较两个字符数组的内容。如果第一个序列中的元素小于第二个序列中的元素,则返回true,否则返回false。这个函数通常可以按词法排序序列,这个序列通常包含字符串。
vector<int>v1 = { 1,2,3,4,5 };
vector<int>v2 = { 1,2,3,4,5 };
vector<int>v3 = { 1,2,3,5,4 };

//
bool result = equal(v1.begin(), v1.end(), v2.begin()); //返回true
bool result = equal(v1.begin(), v1.end(), v3.begin()); //返回false

//
pair<vector<int>::iterator, vector<int>::iterator> p1;
p1 = mismatch(v1.begin(), v1.end(), v3.begin()); //返回数值对
cout << *p1.first << " " << *p1.second; //输出4 5 (*即取地址中存放的元素的值)
cout << (p1.first - v1.begin()); //输出 3 (取迭代器的差值得到实际不同的第一个元素的下标)

//
char c1[10] = "HELLO";
char c2[10] = “BYE BYE”;
result = lexicographical_compare(c1, c1 + 10, c2, c2 + 10);//返回false

3. remove、remove_if、remove_copy、remove_copy_if

  • remove:在一个序列中删除指定值。 不修改vector中的元素个数,也不破坏删除的元素,而是将所有未删除元素放在vector开头。函数返回vector中最后一个未删除元素后面一位的迭代器。从这个迭代器位置到vector末尾的元素数值为未定义(本例中为0)
  • remove_copy:把一个序列中删除指定值后,把该序列复制到指定序列指定位置。 函数返回复制到vector的最后一个元素后面一位的迭代器。
  • remove_if:在一个序列中删除满足指定函数的元素。 不修改vector中的元素个数,也不破坏删除的元素,而是将所有未删除元素放在vector开头。函数返回vector中最后一个未删除元素后面一位的迭代器。从这个迭代器位置到vector末尾的元素数值为未定义(本例中为0)
  • remove_copy_if:在一个序列中删除满足指定函数的元素后,把该序列复制到指定序列指定位置。 函数返回复制到vector的最后一个元素后面一位的迭代器。
vector<int>v1 = { 10,2,10,4,16,6,14,8,12,10 };
vector<int>v2 = { 10,2,10,4,16,6,14,8,12,10 };
vector<int>v3 = { 10,2,10,4,16,6,14,8,12,10 };
vector<int>v4 = { 10,2,10,4,16,6,14,8,12,10 };
vector<int>v0(10, 5);
vector<int>v00(10, 5);

//删除v1中从头到尾范围内所有数值为10的元素。
//v1变成 2 4 16 6 14 8 12 0 0 0,iter指向第一个0的迭代器
vector<int>::iterator iter;
iter=remove(v1.begin(), v1.end(), 10);

//复制v2中从头到尾的所有数值不为10的元素,放在v0中,从v0的begin开始。
修改的对象是第3个参数。
//v0变成  2 4 16 6 14 8 12 5 5 5
remove_copy(v2.begin(), v2.end(), v0.begin(), 10);

//删除v3中从头到尾的,第三个参数(用户自定义的一元判定函数greater9)返回为true的所有元素
//v3变成  2 4 6 8 0 0 0 0 0 0,iter指向第一个0的迭代器
vector<int>::iterator iter;
iter=remove_if(v3.begin(), v3.end(), greater9);

//复制v4中从头到尾的,第三个参数(用户自定义的一元判定函数greater9)返回为true的所有
元素,放在v00中,从v00的begin开始。修改的对象是第3个参数。
//v00变成 2 4 6 8 5 5 5 5 5 5
remove_copy_if(v4.begin(), v4.end(), v00.begin(), greater9);

4. replace、replace_if、replace_copy、replace_copy_if

  • replace:在一个序列中将某个值替换成指定值。
  • replace_copy:把一个序列中将某个值替换成指定值后,把该序列复制到指定序列指定位置。 函数返回复制到vector的最后一个元素后面一位的迭代器。
  • replace_if:在一个序列中将所有满足指定函数的值替换成指定值。
  • replace_copy_if:把一个序列中将所有满足指定函数的值替换成指定值,把该序列复制到指定序列指定位置。 函数返回复制到vector的最后一个 20000 元素后面一位的迭代器。
vector<int>v1 = { 10,2,10,4,16,6,14,8,12,10 };
vector<int>v2 = { 10,2,10,4,16,6,14,8,12,10 };
vector<int>v3 = { 10,2,10,4,16,6,14,8,12,10 };
vector<int>v4 = { 10,2,10,4,16,6,14,8,12,10 };
vector<int>v0(10, 5);
vector<int>v00(10, 5);

//替换v1中从头到尾范围内所有数值为10的元素为100。
//v1变成 100 2 100 4 16 6 14 8 12 100
replace(v1.begin(), v1.end(), 10, 100);

//复制v2中从头到尾的所有元素,将数值10的元素替换成新值100,放在v0中,从v0的begin开始。
修改的对象是第3个参数。
//v0变成  100 2 100 4 16 6 14 8 12 100
replace_copy(v2.begin(), v2.end(), v0.begin(), 10, 100);

//替换v3中从头到尾的,第3个参数(用户自定义的一元判定函数greater9)返回为true的所有元素,
即每个满足greater9的元素都替换成100
//v3变成  100 2 100 4 100 6 100 8 100 100
replace_if(v3.begin(), v3.end(), greater9, 100);

//复制v4中从头到尾的,第3个参数(用户自定义的一元判定函数greater9)返回为true的所有元素
(即每个满足greater9的元素都替换成100),然后放在v0中,从v0的begin开始。修改的对象是第3
个参数。
//v00变成 100 2 100 4 100 6 100 8 100 100
replace_copy_if(v4.begin(), v4.end(), v00.begin(), greater9);

5. 数学算法

  • random_shuffle:对选定范围的元素随机排序。
  • count:对选定范围的元素,为某个数值的元素的个数。
  • count_if:对选定范围的元素,符合条件的元素的个数。
  • min_element:对选定范围的元素,找到最小元素的位置的输入迭代器
  • max_element:对选定范围的元素,找到最大元素的位置的输入迭代器
  • accumulate:对指定范围的所有元素进行特定函数的累加计算。
  • for_each:对指定范围的所有元素进行特定函数操作。
  • transform:对指定范围的所有元素替换成进行特定函数的操作后的元素值。
vector<int>v1 ;

//随机排序v1中从头到尾的元素
random_shuffle(v1.begin(), v1.end());

//计算v1从头到尾元素数值为8的元素个数
int result = count(v1.begin(), v2.end(), 8);

//计算v1从头到尾元素的元素中,判定函数greater9返回为true的元素个数
int result = count_if(v1.begin(), v1.end(), greater9);

//计算v1从头到尾元素的元素中的最小元素,返回最小元素位置的迭代器,若范围为空则
返回迭代器本身
int min = *min_element(v1.begin(), v1.end());

//计算v1从头到尾元素的元素中的最大元素,返回最大元素位置的迭代器,若范围为空则
返回迭代器本身
int max = *max_element(v1.begin(), v1.end());

//计算元素数值和
int sum = accumulate(v1.begin(), v1.end(), 0);

//计算元素数值的平方和
int sum = accumulate(v1.begin(), v1.end(), sumOfSquare);
int sumOfSquare(int accumulator, int currentValue) {
return accumulator + currentValue * currentValue;
}

//对v1从头到尾的每个元素采用常用函数(本例为求平方)
for_each(v1.begin(), v1.end(), outputSquare);
void outputSquare(int value) {
cout << value * value << " ";
}

//对v1从头到尾的每个元素采用常用函数(本例为求立方)进行值的替换,第3个参数制定变换结果
值的存放位置,注意第3个参数可以等于第一个参数
transform(v1.begin(), v1.end(), v1.begin(), calculateCube);
int calculateCube(int value) {
return value * value * value;
}

6. 基本查找和排序算法: find、find_if、sort、binary_search

  • find:在指定序列指定范围的元素中寻找指定数值。返回第1个符合的位置迭代器。
  • find_if:在指定序列指定范围的元素中寻找符合指定函数的元素。返回第1个符合的位置迭代器。
  • sort:对指定序列的指定范围内的元素进行排序。
  • binary_search:判断在指定序列指定范围内是否出现指定值。
vector<int>::iterator loaction;

//寻找v1中从头到尾所有元素中,数值为100的元素,
//函数返回一个输入迭代器,表示第1个包含该值的元素位置或end()
loaction = find(v1.begin(), v1.end(), 100);

//寻找v1中从头到尾所有元素中,一元判定函数greater9返回为true的第1个值。
//函数返回一个输入迭代器,表示第1个greater9返回true的值的元素位置或end()
loaction = find_if(v1.begin(), v1.end(), greater9);

//在给定范围内的元素按升序排列
//函数sort要求随机访问迭代器
sort(v1.begin(), v1.end());

//确定数值13是否在给定范围内的元素的数值之中
bool result=binary_search(v1.begin(), v1.end(), 13);

7. swap、iter_swap、swap_ranges

  • swap:交换指定位置的元素。
  • iter_swap:交换迭代器所指的元素的值。
  • swap_ranges:交换两个指定序列的所有元素。
//交换数组第1个元素和第2个元素
//a[]变成 2 1 3 4 5
int a[] = { 1,2,3,4,5 };
swap(a[0], a[1]);

//函数取两个正向迭代器参数(这里是数组元素的指针),交换迭代器所指元素的值
//a[]变成 2 1 3 4 5
int a[] = { 1,2,3,4,5 };
iter_swap(&a[0], &a[1]);

//交换a开始到a+5(不包括)的元素与从a+5开始的元素
//a[]变成 6 7 8 9 10 1 2 3 4 5
int a[] = { 1,2,3,4,5,6,7,8,9,10 };
swap_ranges(a, a + 5, a + 5);

8. copy、copy_backward、merge、unique、reverse

  • copy:将某个序列指定范围的元素,复制到指定序列v1。返回是复制到指定序列的最后一个元素位置的迭代器,为v1.end()。
  • copy_backward:与copy基本相似。返回的是复制到某序列的最后一个元素位置的迭代器,为v1.begin()。
  • merge:组合两个序列,并复制到一个指定序列中。
  • unique:去除重复值,只保留一个副本。
  • reverse:对指定序列指定范围的所有元素进行调转。
vector<int>v1 = { 1,2,3,9 };
vector<int>v2 = { 4,7,8,8,10 };
vector<int>v3 = { 1,3,5,1,3,5 };
vector<int>result1,result3;
vector<int>result2(10);

//将v1中从头到尾所有元素复制到result1,从result1.begin()开始从前往后开始复制
//函数返回result.begin()(若是copy函数返回result.end())
//result1变成 1 2 3 9
copy(v1.begin(), v1.end(), result1.begin());

//将v1中从头到尾所有元素复制到result1,从result1.end()开始从后往前开始复制
//函数返回result.begin()(若是copy函数返回result.end())
//result1变成 1 2 3 9
copy_backward(v1.begin(), v1.end(), result1.end());

//组合v1,v2序列,复制所有元素到result2的开头处。
//如果在merge操作之前未对结果序列分配足够的长度,可以用back_inserter
//back_inserter调用容器默认的push_back函数,在末尾插入一个元素
//result2变成 1 2 3 4 7 8 8 9 10
merge(v1.begin(), v1.end(), v2.begin(), v2.end(), result2.begin());
或
merge(v1.begin(), v1.end(), v2.begin(), v2.end(), back_inserter(result3));

//去除重复值,序列中每个值只有1个副本,不改变元素个数,去除的元素放在最后,设为未定义
//v2变成 4 7 8 10 0
unique(v2.begin(), v2.end());

//将给定范围的所有元素调转顺序
//v1变成 9 3 2 1
reverse(v1.begin(), v1.end());
vector<int>::iterator loaction;
loaction=find(v1.begin(),v1.end(),100);
loaction=find_if(v1.begin(),v1.end(),greater9);

9. inplace_merge、unique_copy、reverse_copy

  • inplace_merge:合并同一容器中的两个已排序的元素序列。
  • unique_copy:复制某个序列某个范围去重后的所有元素,放入指定序列指定位置后。
  • reverse_copy:复制某个序列某个范围调转后的所有元素,放入指定序列指定位置后。
vector<int>v2 = { 4,7,8,8,10 };
vector<int>v3 = { 1,3,5,1,3,5 };
vector<int>result3;

//合并同一容器中的两个排序元素序列
//v3变成 1 1 3 3 5 5
inplace_merge(v3.begin(),v3.begin()+3,v3.end());

//复制v2从头到尾的去重后的所有元素,放入result3中
//操作之前若未对结果序列分配足够的长度,用back_inserter
//result3变成 4 7 8 10
unique_copy(v2.begin(), v2.end(), result3.begin());、
或
unique_copy(v2.begin(), v2.end(), back_inserter(result3));

//复制v2从头到尾所有元素,调转顺序,放入result3中
//操作之前未对结果序列分配足够的长度,用back_inserter
//result3变成 10 8 8 7 4
reverse_copy(v2.begin(), v2.end(), result3.begin());
或
reverse_copy(v2.begin(), v2.end(), back_inserter(result3));

10. 集合操作:includes、set_difference、set_intersection、set_symmetric_difference、set_union

  • includes:确认第2个集合的每个元素是否都在第1个集合中。
  • set_difference:求差集。确定在第1个集合中而不在第2个集合中的元素。
  • set_intersection:求交集。确定在第1个集合中也在第2个集合中的元素。
  • set_symmetric_difference:求相互的差集。在1不在2元素 + 在2不在1元素。
  • set_union:求并集。在1出现过的元素和在2出现过的元素,去重之后复制
int a1[] = { 1,2,3,4,5,6,7,8,9,10 };
int a2[] = { 1,2,3,4,5};
int a3[] = { 1,2,6,7,8};
int b1[10], b2[10], b3[10], b4[10];

//确认第2个集合的每个元素是否都在第1个集合中,返回bool值
bool result = includes(a1, a1 + 10, a2, a2 + 5);

//求差集。确定在第1个集合中而不在第2个集合中的元素。
//返回一个输出迭代器,放在最后复制值的后面
//b1变成 6 7 8 9 10
int *ptr1 = set_difference(a1, a1 + 10, a2, a2 + 5, b1);

//求交集。确定在第1个集合中也在第2个集合中的元素。
//返回一个输出迭代器,放在最后复制值的后面
//b2变成 1 2 3 4 5
int *ptr2 = set_intersection(a1, a1 + 10, a2, a2 + 5, b2);

//求相互的差集。在1不在2元素 + 在2不在1元素
//返回一个输出迭代器,放在最后复制值的后面
//b3变成 3 4 5 6 7 8
int *ptr3 = set_symmetric_difference(a2, a2 + 5, a3, a3 + 5, b3);

//求并集。在1出现过的元素和在2出现过的元素,去重之后复制
//返回一个输出迭代器,放在最后复制值的后面
//b4变成 1 2 3 4 5 6 7 8
int *ptr4 = set_union(a2, a2 + 5, a3, a3 + 5, b4);

11. lower_bound、upper_bound、equal_range

  • lower_bound:找到在某序列某范围内插入指定值后,仍能保持升序的第1个位置。返回该位置迭代器。
  • upper_bound:找到在某序列某范围内插入指定值后,仍能保持升序的最后1个位置。返回该位置迭代器。
  • equal_range:找到在某序列某范围内插入指定值后,仍能保持升序的第1个位置和最后1个位置。返回该位置迭代器对。
vector<int>v1 = { 2,2,4,4,6,6,6,8 };

//确定在v1给定范围内插入6后,仍能保持升序的第1个位置
//函数返回一个正向迭代器,指向插入的位
vector<int>::iterator lower;
lower=lower_bound(v1.begin(), v1.end(), 6);
cout << lower - v1.begin(); //输出4

//确定在v1给定范围内插入6后,仍能保持升序的最后1个位置
//函数返回一个正向迭代器,指向插入的位置
vector<int>::iterator upper;
upper = upper_bound(v1.begin(), v1.end(), 6);
cout << upper - v1.begin(); //输出7

//返回一个正向迭代器对pair(first,second),包含lower_bound和upper_bound操作的组合结果
pair<vector<int>::iterator, vector<int>::iterator> eq;
eq = equal_range(v1.begin(), v1.end(), 6);
cout << eq.first - v1.begin() << " " << eq.second - v1.begin(); //输出 4 7

12. 堆排序:make_heap、sort_heap、push_heap、pop_heap

  • make_heap:对指定序列(数组、vector、deque)建造最大堆。
  • sort_heap:升序排列。
  • push_heap:在堆中增加新值(保持最大堆)。
  • pop_heap:去掉堆顶元素(保持最大堆)。

参数应为随机访问迭代器,因此只适用于数组、vector、deque

vector<int>nums = { 3,100,52,77,22,31,1,98,13,40 };
vector<int>v;

//建造最大堆
//nums变成 100 98 52 77 40 31 1 3 13 22
make_heap(nums.begin(), nums.end());

//升序排序
//nums变成 1 3 13 22 31 40 52 77 98 100
sort_heap(nums.begin(), nums.end());

//在堆中增加新值
for (int i = 0; i < nums.size(); i++) {
v.push_back(nums[i]);
push_heap(v.begin(), v.end());
}
vector<int>nums = { 3,100,52,77,22,31,1,98,13,40 };
//新增3,输出v:3
//新增100,输出v:100 3
//新增52,输出v:100 3 52
//新增77,输出v:100 77 52 3
//新增22,输出v:100 77 52 3 22
//新增31,输出v:100 77 52 3 22 31
//新增1,输出v:100 77 52 3 22 31 1
//新增98,输出v:100 98 52 77 22 31 1 3
//新增13,输出v:100 98 52 77 22 31 1 3 13
//新增40,输出v:100 98 52 77 40 31 1 3 13 22

//在堆中删除堆顶元素,操作后是按升序排列的。
for (int i = 0; i < v.size(); i++) {
pop_heap(v.begin(), v.end()-i);
}

//删除栈顶100,输出v:98 77 52 22 40 31 1 3 13 100
//删除栈顶98,输出v:77 40 52 22 13 31 1 3 98 100
//删除栈顶77,输出v:52 40 31 22 13 3 1 77 98 100
//删除栈顶52,输出v:40 22 31 1 13 3 52 77 98 100
//删除栈顶40,输出v:31 22 3 1 13 40 52 77 98 100
//删除栈顶31,输出v:22 13 3 1 31 40 52 77 98 100
//删除栈顶22,输出v:13 1 3 22 31 40 52 77 98 100
//删除栈顶13,输出v:3 1 13 22 31 40 52 77 98 100
//删除栈顶3  ,输出v:1 3 13 22 31 40 52 77 98 100
//删除栈顶1  ,输出v:1 3 13 22 31 40 52 77 98 100

13. min、max

  • min:对两个输入参数比较大小,输出较小的
  • max:对两个输入参数比较大小,输出较大的
cout<<min(12,7);  //输出7

14. 其他算法

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: