STL常用函数应用举例

STL常用函数应用举例

备忘录

  • 只要明白函数的作用,一般即可以联想到其参数。

  • 像unique(), remove()这类的函数需要注意,对容器进行操作后不会改变原有的元素个数,可以通过函数返回的迭代器进行下一步操作。

  • 对于一些会改变元素个数的操作,如merger(),结果需要放到一个新的容器里面,并且传参时仅需开始迭代器。

  • 对于copy类函数:存放结果的容器串传参时只需开始迭代器;必须保证有足够的大小,否则易运行时引发错误。

  • 对于某些对操作两个等长序列操作的函数(如mismatch()、equal() ),第二个序列无需传入结束迭代器。但是必须保证第二个序列的长度不比第一个小,否则会引发越界错误。

  • 一些函数的使用是有前提的,例如binary_search()必须在有序的序列上使用,heap_sort()需要保证序列符合堆的结构。

  • 一些需要特别记住参数使用的函数:

1.注意结果将会存储在指定的另一个范围内。
2.注意第四个参数的使用(返回新的值)
transform(ary1.begin(), ary1.end, ary2.begin(), [](int a){return a * 2; });

注意是三个参数,并且结束迭代器放在第三个。
rotate(ary.begin(), ary.begin() + 5, ary.end());

代码

#pragma warning(disable : 4996)
#include<iostream>
#include<vector>
#include<algorithm>
#include<random>
#include<time.h>
#include<string>
#define ARRAY vector<int>	//下标从0开始有效
using namespace std;

void printArray(ARRAY &a){
	for (int i = 0; i < a.size(); i++) {
		cout << a[i] << " ";
	}
	cout << endl;
}

/*
lower_bound() 找到大于等于某值的第一次出现
upper_bound() 找到大于某值的第一次出现
*/
void test_Bound(){
	cout << "在一个已排序的序列中找到某个值出现的次数" << endl;
	ARRAY ary{1,4,5,6,7,8,8,8,8,9,9,9,11,19};
	sort(ary.begin(), ary.end());
	int val = 8;
	auto start = upper_bound(ary.begin(), ary.end(), val);
	auto end = lower_bound(ary.begin(), ary.end(), val);
	cout << start - end << endl;
	return;
}

/*
binary_search() 在有序序列中确定给定元素是否存在
*/
void test_BinarySearch(){
	cout << "搜索某个已排序序列中是否存在某个值" << endl;
	ARRAY ary{ 1, 4, 5, 6, 7, 8, 8, 8, 8, 9, 9, 9, 11, 19 };
	sort(ary.begin(), ary.end());
	bool find = binary_search(ary.begin(), ary.end(), 11);	//注意返回值不是迭代器或下标,而是bool
	cout << (find ? "Found" : "NotFound") << endl;
	return;
}

/*
min_element(a,a+n) 序列中的最小元素
max_element() 序列中的最大元素
*/
void test_MinElement(){
	cout << "找到序列中求余8后结果最小的数" << endl;
	ARRAY ary{ 5, 7, 11, 19, 31, 37, 74};
	sort(ary.begin(), ary.end());
	auto it = min_element(ary.begin(), ary.end(), [](int a, int b){return a%8 < b%8; });
	cout << *it << endl;
	return;
}

/*
unique() 的功能是去除相邻的重复元素,其实它并不真正把重复的元素删除,是把重复的元素移到后面去了,
然后依然保存到了原数组中,然后 返回去重后最后一个元素的地址.(注意顺序不会改变)
unique_copy()复制并非仅复制不重复的元素到指定数组,而是将unique()产生的结果复制过去,注意若
容器数组长度不够会引发错误。
*/
void test_Unique(){
	ARRAY ary{ 4,4,4,2,2,2,3,3,3};
	auto last = unique(ary.begin(), ary.end());
	for (auto it = ary.begin(); it < last; it++) cout << *it << " ";
	ARRAY ary2(20, -1);		
	unique_copy(ary.begin(), ary.end(), ary2.begin());
	printArray(ary2);
	return;
}

/*
mismatch(), 找出两个序列相异的第一个元素,返回一个记录两个迭代器的pair
1.注意参数,第二个数组没有结束迭代器,判断的长度以第一个数组的长度为准,使用不但可能会引发越界错误。
2.注意相同的情况下返回结束迭代器,读取值时报错。
equal_range(),是C++ STL中的一种二分查找的算法,需要在以排序的数组中使用,它通过一个Pair返回lower_bound()
和upper_bound()的结果。
*/
void testCompare(){
	cout << "找出两个序列中第一对不同的元素" << endl;
	ARRAY ary1{ 1, 2, 4, 6, 11, 33, 44, 66};
	ARRAY ary2{ 1, 2, 4, 6, 12, 33, 44, 66, 99 };
	ARRAY ary3{ 1, 2, 3, 4, 4, 4, 5, 5, 5, 5, 6, 7, 8, 9 };
	pair<ARRAY::iterator,ARRAY::iterator> diffIdx = mismatch(ary1.begin(), ary1.end(), ary2.begin());
	if (diffIdx.first == ary1.end() || diffIdx.second == ary2.end()) { 
		cout << "Total same!" << endl;
	}
	else{
		printf("%d  %d\n", *diffIdx.first, *diffIdx.second);
	}
	cout << "使用equal()判断序列是否相等" << endl;
	bool same = equal(ary1.begin(), ary1.end(), ary3.begin());
	cout << (same ? "Same" : "NotSame") << endl;
	cout << "使用equal_rang()找到序列中某值出现的范围" << endl;
	pair<ARRAY::iterator, ARRAY::iterator>  idx = equal_range(ary3.begin(), ary3.end(), 5);
	if (idx.first == ary3.end() || idx.second == ary3.end()) {
		cout << "Not Found!" << endl;
	}
	else{
		printf("%d  %d\n", idx.first-ary3.begin(), idx.second-ary3.begin());
	}
	return;
}


/*
transform在指定的范围内应用于给定的操作,并将结果存储在指定的另一个范围内,注意第四个参数的使用
*/
void test_transform(){
	cout << "将ary1前5个元素×11后复制到ary2" << endl;
	ARRAY ary1{ 1, 2, 4, 6, 11, 33, 44, 66 };
	ARRAY ary2(10, -1);
	transform(ary1.begin(), ary1.begin() + 5, ary2.begin(), [](int a){return a * 11; });
	printArray(ary2);
}

/*
rotate() 的第一个参数是这个序列的开始迭代器;第二个参数是指向新的第一个元素的迭代器,它必定在序列之内。第三个参数是这个序列的结束迭代器。
rotate() 操作会导致一个新元素成为开始迭代器所指向的第一个元素。在旋转之后,最后一个元素会在新的第一个元素之前。
*/
void test_roate(){
	cout << "使用roate()旋转数组" << endl;
	ARRAY ary{ 1,2,3,4,5,6,7,8,9};
	rotate(ary.begin(), ary.begin() + 5, ary.end());
	printArray(ary);
}

/*
交换的容器内部元素进行随机排列
注意函数必须与标准库默认的随机生成器一起使用,否则结果每次都一样。
*/
void test_shuffle(){
	cout << "使用shuffle()来打乱数组的顺序" << endl;
	ARRAY ary{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	srand(time(NULL));
	random_shuffle(ary.begin(), ary.end());
	printArray(ary);
}

/*
将满足某谓词的元素都放到前面
*/
void test_partition(){
	cout << "使用partition()来划分数组" << endl;
	ARRAY ary{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	ARRAY::iterator it = partition(ary.begin(), ary.end(), [](int a){return a % 2 == 1; });
	for (auto i = ary.begin(); i < it; i++){
		cout << *i << " ";
	}
	cout << endl;
	printArray(ary);
	return;
}

/*
merger()归并两个有序序列,注意合并后的结果放到一个新的容器之中,并且无需结束迭代器
*/
void test_merger(){
	cout << "使用merger()合并两个有序序列" << endl;
	ARRAY ary1{ 1, 4, 6, 8, 11, 14, 16, 18 };
	ARRAY ary2{2,5,7,8,12,15,17,18};
	ARRAY result(ary1.size() + ary2.size());
	merge(ary1.begin(), ary1.end(), ary2.begin(), ary2.end(), result.begin());
	printArray(result);
	return;
}

/*
includes(): 如果第一个集合中的全部元素都来自第二个集合,它会返回 true。如果第二个集合是空的集合,它也返回 true。
注意数据需要经过排序,否则可能出现运行错误。
set_union() 函数模板实现了集合的并集运算,它需要 5 个参数。
set_intersection() 构造两个集合的有序交集,用法和 set_union() 相同,
set_difference() 构造两个集合的有序差集
set_symmetric_difference() 构造两个集合的有序对称差集(并-交)
*/
void test_set(){
	cout << "用include()来判断有序集合的包含关系" << endl;
	ARRAY ary1{ 1, 2, 4,6,8,10 };
	ARRAY ary2{ 4, 6, 10 };
	ARRAY ary3{ 1, 10, 100, 1000 };
	bool isInclude = includes(ary1.begin(), ary1.end(), ary2.begin(), ary2.end());
	cout << (isInclude ? "Yes" : "No") << endl;

	cout << "用set_union()来实现并集运算" << endl;
	ARRAY res1(ary1.size() + ary2.size(), -1);
	set_union(ary1.begin(), ary1.end(), ary3.begin(), ary3.end(), res1.begin());
	printArray(res1);

	cout << "用set_intersection()来实现差集运算" << endl;
	ARRAY res3(ary1.size() + ary2.size(), -1);
	set_difference(ary1.begin(), ary1.end(), ary2.begin(), ary2.end(), res3.begin());
	printArray(res3);

	cout << "用set_symmetric_difference()来实现对称差集运算" << endl;
	ARRAY res4(ary1.size() + ary3.size(), -1);
	set_intersection(ary1.begin(), ary1.end(), ary3.begin(), ary3.end(), res3.begin());
	printArray(res3);

	return;
}


/*
为了向堆中添加元素,首先可以用任何方法将元素附加到序列中。然后调用 push_heap() 恢复堆的排序。
pop_heap() 函数将第一个元素移到最后,并保证剩下的元素仍然是一个堆。然后就可以使用 vector 的成员函数 pop_back() 移除最后一个元素。
sort_heap() 会将元素段作为堆来排序。如果元素段不是堆,程序会在运行时崩溃。
*/
void test_heap(){
	cout << "构造大顶堆" << endl;
	ARRAY ary{ 1, 2, 4, 6, 12, 33, 44, 66, 99 };
	make_heap(ary.begin(), ary.end());
	printArray(ary);
	cout << "向堆中插入元素" << endl;
	ary.push_back(1000);
	push_heap(ary.begin(), ary.end());
	printArray(ary);
	cout << "移除堆元素" << endl;
	pop_heap(ary.begin(), ary.end());
	ary.pop_back();
	printArray(ary);
	cout << "对堆进行排序" << endl;
	sort_heap(ary.begin(), ary.end());
	printArray(ary);
	return;
}

/*
next_permutation、prev_permutation分别给出按字典序的下一个排列和上一个序列。
注意在使用前需要对欲排列数组排序,否则只能找出该序列之后的全排列数。
*/
void test_premutation(){
	string arg = "1234";
	cout << "next_permutation" << endl;
	while (next_permutation(arg.begin(), arg.end())){
		cout << arg << endl;
	}
	cout << "prev_permutation" << endl;
	arg = "4321";
	while (prev_permutation(arg.begin(), arg.end())){
		cout << arg << endl;
	}
	return;
}

/*
需要注意:移除操作不会改变被“移除”元素的序列的元素个数!
基本上每个元素都是通过用它后面的元素覆盖它来实现移除的。
*/
void test_other(){
	cout << "反转元素的次序" << endl;
	ARRAY ary{ 1, 2, 4, 6, 12, 33, 44, 66, 99 };
	reverse(ary.begin(), ary.end());
	printArray(ary);
	cout << "计算奇数个数" << endl;
	int number = count_if(ary.begin(), ary.end(), [](int i){return i % 2 == 1; });
	cout << number << endl;
	cout << "将所有偶数替换" << endl;
	replace_if(ary.begin(), ary.end(), [](int i){return i % 2 == 1; }, -99);
	printArray(ary);
	cout << "'假移除'所有-99" << endl;
	auto tail = remove_if(ary.begin(), ary.end(), [](int i){return i == -99; });
	for (auto it = ary.begin(); it < tail; it++) {
		cout << *it << " ";
	}
	cout << endl;
	cout << "真正完成移除操作" << endl;
	ary.erase(tail, ary.end());
	printArray(ary);
	return;
}

int main(){
	//test_Bound();
	//test_BinarySearch();
	//test_MinElement();
	//test_Unique();
	//testCompare();
	//test_transform();
	//test_roate();
	//test_shuffle();
	//test_partition();
	//test_merger();
	//test_set();
	//test_heap();
	//test_premutation();
	test_other();
	return 0;
}
发布了90 篇原创文章 · 获赞 31 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/BlackCarDriver/article/details/104656306