【跟学C++】C++STL标准模板库——算法整理(上)(Study18)

news2024/11/15 8:48:58

文章目录

    • 1、STL简介
    • 2、STL算法分类及常用函数
      • 2.1、非变序算法
        • 2.1.1 计数算法(2个)
        • 2.1.2 搜索算法(7个)
        • 2.1.3 比较算法(2个)
      • 3、总结

 ============================ 【说明】 ===================================================
  大家好,本专栏主要是跟学C++内容,自己学习了这位博主【 AI菌】的【C++21天养成计划】,讲的十分清晰,适合小白,希望给这位博主多点关注、收藏、点赞。
  主要针对所学内容,通过自己的理解进行整理,希望大家积极交流、探讨,多给意见。后面也会给大家更新,其他一些知识。若有侵权,联系删除!共同维护网络知识权利!
 =======================================================================================
   写在前面
  至此,我们了解了C++的基本语法,但是进一步学习C++,数据结构是必不可少的内容。 数据结构与算法决定了代码测存储方式,以及代码执行效率。
  数据结构的重要性不言而喻, 关于数据结构的基本知识可以转至本人另一专栏====>【 数据结构】。同样也可以阅读博主【 AI菌】写的【 数据结构与算法】,比较通俗易懂,可以学习学习!


1、STL简介

  前面几节,我们学了很多模板类,包括list、stack、queue、vector、string、set、map等等都是属于STL模板库
  同时,STL模板库也提供了很多实用的函数,这些函数通过引用头文件#include<algorithm>即可方便使用,它和之前讲的各种类的成员函数使用方法一致,有效的提升代码效率。
  在程序设计过程中,我们会常用到查找、删除、搜素、计数等算法。C++中在STL模板库中已经提供这些函数,但是在使用之前必须加上头文件:

#include<algorithm>

2、STL算法分类及常用函数

  STL算法模板库分为两大类:非变序与变序。对于这两种类别如何理解?下面就详细介绍两大类以及各函数的具体应用。

2.1、非变序算法

  非变序算法就是不会改变容器内元素的书顺序与内容。常见的非变序算法有:
  

2.1.1 计数算法(2个)

函数名解释
count()在一定范围内,查找与指定值匹配的所有元素。
count_if()在一定范围内,产值满足条件的所有元素。

  count()和count_ if()计算给定范围内的元素数。
  count()计算包含给定值的元素值。
  count_ if():计算满足通过参数传递的一元谓词(可以是函数对象,也可以是lambda表达式)。

#include <iostream>
#include <map>
#include<list>
#include<functional>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;

//初始vec
void Display(vector<int> vec) {
	for (int i = 0; i < vec.size(); i++)
	{
		cout << vec[i] << " ";
	}
	cout << endl;
}

//偶数判断
template <typename elementType>
bool IsEven(const elementType &number) {
	return ((number % 2) == 0);
}
int main计数() {
	vector<int> vec;
	for (int value = 0; value < 10; ++value)
		vec.push_back(value);
	cout << "原始的vec是:" << endl;
	Display(vec);


	//===============计数算法==================
	//1、count

	size_t nNumZero = count(vec.begin(), vec.end(), 0);
	cout << "数组vec中值为0的个数:" << nNumZero << endl;

	//2、count_if
	size_t nNumEvenElements = count_if(vec.begin(),vec.end(),IsEven<int>);
	cout << "数组vec中偶数的个数:" << nNumEvenElements << endl;
	return 0;

}

在这里插入图片描述
  

2.1.2 搜索算法(7个)

函数名解释
search()在一定范围内,根据元素相等性(或指定二元谓词)搜索第一个满足条件的元素。
search_n()在一定范围内,搜索与指定值相等或满足指定谓词的n个元素
find()在一定范围内,搜索与指定值相等/匹配的第一个元素
find_if()在一定范围内,搜索满足条件的第一个元素
find_end()在一定范围内,搜索最后一个满足特定条件的元素。 常用于在序列 A 中查找序列 B 最后一次出现的位置。
find_first_of()在一定范围内,搜索指定序列中的任何一个元素第一次出现的位置;在另一重载版本中,搜索满足指定条件的第一个元素常用于在 A 序列中查找和 B 序列中任意元素相匹配的第一个元素
adjacent_find()在集合中搜索两个相等或满足条件的元素。常用于在指定范围内查找 2 个连续相等的元素

  (1) search()/search_n()

  如果需要查找一个序列或模式; 在这种情况下,应该使用serach()search_n()

  1search():用于在一个序列中查找另一个序列,比如在数组vec中查找list序列的位置。search() 函数也提供有以下 2 种语法格式:

序列 A:1,2,3,4,5,1,2,3,4,5
序列 B:1,2,3
//查找 [first1, last1) 范围内第一个 [first2, last2) 子序列
ForwardIterator search (ForwardIterator first1, ForwardIterator last1,ForwardIterator first2, 
						ForwardIterator last2);
//查找 [first1, last1) 范围内,和 [first2, last2) 序列满足 pred 规则的第一个子序列
ForwardIterator search (ForwardIterator first1, ForwardIterator last1, ForwardIterator first2, 	
						ForwardIterator last2,BinaryPredicate pred);

  其中,各个参数的含义分别为:
    first1、last1:都为正向迭代器,其组合 [first1, last1) 用于指定查找范围(也就是上面例子中的序列 A);
    first2、last2:都为正向迭代器,其组合 [first2, last2) 用于指定要查找的序列(也就是上面例子中的序列 B);
    pred:用于自定义查找规则。该规则实际上是一个包含 2 个参数且返回值类型为 bool 的函数(第一个参数接收 [first1, last1) 范围内的元素,第二个参数接收 [first2, last2) 范围内的元素)。函数定义的形式可以是普通函数,也可以是函数对象。

  2search_n():和 search() 一样,search_n() 用于在指定区域内查找第一个符合要求的子序列。不同之处在于,前者查找的子序列中可包含多个不同的元素,而后者查找的只能是包含多个相同元素的子序列。用于在一个容器中查找n个相邻的指定值。search_n() 函数的语法格式如下:

序列 A:1,2,3,4,4,4,1,2,3,4,4,4
序列 B:1,2,3
序列 C:4,4,4
//在 [first, last] 中查找 count 个 val 第一次连续出现的位置
ForwardIterator search_n (ForwardIterator first, ForwardIterator last,
                          Size count, const T& val);
//在 [first, last] 中查找第一个序列,该序列和 count 个 val 满足 pred 匹配规则
ForwardIterator search_n ( ForwardIterator first, ForwardIterator last,
                           Size count, const T& val, BinaryPredicate pred );

  其中,各个参数的含义分别为:
    first、last:都为正向迭代器,其组合 [first, last) 用于指定查找范围(也就是上面例子中的序列 A);
    count、val:指定要查找的元素个数和元素值,以上面的序列 B 为例,该序列实际上就是 3 个元素 4,其中 count 为 3,val 为 4;
    pred:用于自定义查找规则。该规则实际上是一个包含 2 个参数且返回值类型为 bool 的函数(第一个参数接收[first, last) 范围内的元素,第二个参数接收 val)。函数定义的形式可以是普通函数,也可以是函数对象。

  
  关于search()search_n()案例如下:

#include <iostream>
#include <map>
#include<list>
#include<functional>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;

template <typename T>
//初始ec
void Display2(const T& Input) {

	for (auto i = Input.begin(); i != Input.end(); i++)
	{
		cout << *i << " ";
	}
	cout << endl;
}


int main() {
	vector<int> vec;
	for (int value = 0; value < 10; ++value)
		vec.push_back(value);
		
	vec.push_back(9);
	vec.push_back(9);
	cout << "原始的vec是:" << endl;
	Display2(vec);


	list <int> listNums;
	for (int j = 4; j < 9; j++)
	{
		listNums.push_back(j);
	}
	cout << "原始的list是:" << endl;
	Display2(listNums);

	//===============查找算法==================
	//1、search
	auto isRange = search(vec.begin(), vec.end(), listNums.begin(), listNums.end());
	if (isRange != vec.end())
		cout << "listNums find in vec at position:" << distance(vec.begin(), isRange) << endl;
	else
		cout << "No Find!" << endl;
	
	cout << "================" << endl;
	
	//===============查找算法==================
	//1、search_n
	auto iFound = search_n(vec.begin(), vec.end(), 3, 9);
	if (iFound != vec.end())
		cout << "999 found in vec at position:" << distance(vec.begin(), iFound) << endl;
	else
		cout << "No Find!" << endl;

	return 0;
}

在这里插入图片描述

  
  (2) find()/find_if()

  1find():在相关容器中查找与值匹配的元素。 find() 函数的语法格式:

InputIterator find (InputIterator first, InputIterator last, const T& val);

  其中,first 和 last 为输入迭代器,[first, last) 用于指定该函数的查找范围;val 为要查找的目标元素。

  
  2find_ if(): 和find() 函数相同,find_if() 函数也用于在指定区域内执行查找操作。不同的是,前者需要明确指定要查找的元素的值,而后者则允许自定义查找规则。
  自定义查找规则,实际上指的是有一个形参且返回值类型为 bool 的函数。值得一提的是,该函数可以是一个普通函数(又称为一元谓词函数),比如:

bool mycomp(int i) {
  return ((i%2)==1);
}

  上面的 mycomp() 就是一个一元谓词函数,其可用来判断一个整数是奇数还是偶数。也可以是一个函数对象,比如:

//以函数对象的形式定义一个 find_if() 函数的查找规则
class mycomp2 {
public:
    bool operator()(const int& i) {
        return ((i % 2) == 1);
    }
};

  此函数对象的功能和 mycomp() 函数一样。确切地说,find_if() 函数会根据指定的查找规则,在指定区域内查找第一个符合该函数要求(使函数返回 true)的元素。

find_if() 函数的语法格式如下:

InputIterator find_if (InputIterator first, InputIterator last, UnaryPredicate pred);

  其中,first 和 last 都为输入迭代器,其组合 [first, last) 用于指定要查找的区域;pred 用于自定义查找规则。

  
  关于find()find_if()案例如下:

#include <iostream>
#include <map>
#include<list>
#include<functional>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;

//初始vec
void Display(vector<int> vec) {

	for (int i = 0; i < vec.size(); i++)
	{
		cout << vec[i] << " ";
	}
	cout << endl;
}

//偶数判断
template <typename elementType>
bool IsEven(const elementType &number) {

	return ((number % 2) == 0);
}

//===========查找1---find()/find_if()====================
int main()
{
	vector<int> vec;
	for (int value = 0; value < 10; ++value)
		vec.push_back(value);
	cout << "原始的vec是:" << endl;
	Display(vec);

	//===============查找算法==================
	//1、find
	auto isFind = find(vec.begin(), vec.end(), 5);
	if (isFind != vec.end())
		cout << "Find the number:" << *isFind << endl;
	else
		cout << "No find!" << endl;


	//===============查找算法==================
	//1、find_if
	//查找第一个偶数元素
	auto isFindEven = find_if(vec.begin(), vec.end(), IsEven<int>);
	if (isFindEven != vec.end())
		cout << "The first even number is " << *isFindEven << endl;
	else
		cout << "No Find!" << endl;
	
	return 0;
}

在这里插入图片描述

  
  (3) find_end()
  find_end() 函数常用于在序列 A 中查找序列 B 最后一次出现的位置。find_end() 函数的语法格式有 2 种:

序列 A:1,2,3,4,5,1,2,3,4,5
序列 B:1,2,3
//查找序列 [first1, last1) 中最后一个子序列 [first2, last2)
ForwardIterator find_end (ForwardIterator first1, ForwardIterator last1,
                          ForwardIterator first2, ForwardIterator last2);
//查找序列 [first2, last2) 中,和 [first2, last2) 序列满足 pred 规则的最后一个子序列
ForwardIterator find_end (ForwardIterator first1, ForwardIterator last1,
                          ForwardIterator first2, ForwardIterator last2,
                          BinaryPredicate pred);

  其中,各个参数的含义如下:
    first1、last1:都为正向迭代器,其组合 [first1, last1) 用于指定查找范围(也就是上面例子中的序列 A);
    first2、last2:都为正向迭代器,其组合 [first2, last2) 用于指定要查找的序列(也就是上面例子中的序列 B);
    pred:用于自定义查找规则。该规则实际上是一个包含 2 个参数且返回值类型为 bool 的函数(第一个参数接收 [first1, last1) 范围内的元素,第二个参数接收 [first2, last2) 范围内的元素)。函数定义的形式可以是普通函数,也可以是函数对象。

  
  关于find_end()案例如下:

#include <iostream>
#include <map>
#include<list>
#include<functional>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;

//===========查找2---find_end()=====================

//以普通函数的形式定义一个匹配规则
bool mycomp1(int i, int j) {
	return (i%j == 0);
}

//以函数对象的形式定义一个匹配规则
class mycomp2 {
public:
	bool operator()(const int& i, const int& j) {
		return (i%j == 0);
	}
};

int main() {
	vector<int> myvector{ 1,2,3,4,8,12,18,1,2,3 };
	int myarr[] = { 1,2,3 };
	//调用第一种语法格式
	vector<int>::iterator it = find_end(myvector.begin(), myvector.end(), myarr, myarr + 3);
	if (it != myvector.end()) {
		cout << "最后一个{1,2,3}的起始位置为:" << it - myvector.begin() << ",*it = " << *it << endl;
	}

	int myarr2[] = { 2,4,6 };
	//调用第二种语法格式
	it = find_end(myvector.begin(), myvector.end(), myarr2, myarr2 + 3, mycomp2());
	if (it != myvector.end()) {
		cout << "最后一个能分别被 {2、4、6} 中的元素整除的起始位置为:" << it - myvector.begin() << ",*it = " << *it<<endl;
	}
	return 0;
}

在这里插入图片描述
  上面程序中共调用了 2 次 find_end() 函数:
  第一次调用了第一种语法格式的 find_end() 函数,其功能是在 myvector 容器中查找和 {1,2,3} 相等的最后一个子序列,显然最后一个 {1,2,3} 中元素 1 的位置下标为 7(myvector 容器下标从 0 开始);
  第二次调用了第二种格式的 find_end() 函数,其匹配规则为 mycomp2,即在 myvector 容器中找到最后一个子序列,该序列中的元素能分别被 {2、4、6} 中的元素整除。显然,myvector 容器中 {4,8,12} 和 {8,12,18} 都符合,该函数会找到后者并返回一个指向元素 8 的迭代器。

  
  (4) find_first_of()
  find_first_of():在某些情境中,我们可能需要在 A 序列中查找和 B 序列中任意元素相匹配的第一个元素,这时就可以使用 find_first_of() 函数。find_first_of() 函数有 2 种语法格式,分别是:

//以判断两者相等作为匹配规则
InputIterator find_first_of (InputIterator first1, InputIterator last1,
                             ForwardIterator first2, ForwardIterator last2);
//以 pred 作为匹配规则
InputIterator find_first_of (InputIterator first1, InputIterator last1,
                             ForwardIterator first2, ForwardIterator last2,
                             BinaryPredicate pred);

  其中,各个参数的含义如下:
    first1、last1:都为输入迭代器,它们的组合 [first1, last1) 用于指定该函数要查找的范围;
    first2、last2:都为正向迭代器,它们的组合 [first2, last2) 用于指定要进行匹配的元素所在的范围;
    pred:可接收一个包含 2 个形参且返回值类型为 bool 的函数,该函数可以是普通函数(又称为二元谓词函数),也可以是函数对象。

  不同语法格式的匹配规则也是不同的:
  第 1 种语法格式:逐个取 [first1, last1) 范围内的元素(假设为 A),和 [first2, last2) 中的每个元素(假设为 B)做 A==B 运算,如果成立则匹配成功;
  第 2 种语法格式:逐个取 [first1, last1) 范围内的元素(假设为 A),和 [first2, last2) 中的每个元素(假设为 B)一起带入 pred(A, B) 谓词函数,如果函数返回 true 则匹配成功。

  
  关于find_first_of()案例如下:

#include <iostream>     // std::cout
#include <algorithm>    // std::find_first_of
#include <vector>       // std::vector
using namespace std;
//===========查找4---find_first_of=====================

// 自定义二元谓词函数,作为 find_first_of() 函数的匹配规则
bool mycomp3(int c1, int c2) {
	return (c2 % c1 == 0);
}
//以函数对象的形式定义一个 find_first_of() 函数的匹配规则
class mycomp4 {
public:
	bool operator()(const int& c1, const int& c2) {
		return (c2 % c1 == 0);
	}
};
int main() {
	char url[] = "abcd1dnetstl/";
	char ch[] = "stl";
	//调用第一种语法格式,找到 url 中和 "stl" 任一字符相同的第一个字符
	char *it = find_first_of(url, url + 12, ch, ch + 4);
	if (it != url + 12) {
		cout << "it find in myvector at position: 【" <<distance(url, it) <<"】."<< endl;
		cout << "*it = " << *it << '\n';
		
	}
	vector<int> myvector{ 5,7,3,9 };
	int inter[] = { 4,6,8 };
	//调用第二种语法格式,找到 myvector 容器中和 4,6,8任一元素有 c2%c1=0 关系的第一个元素,即6%3
	vector<int>::iterator iter = find_first_of(myvector.begin(), myvector.end(), inter, inter + 3, mycomp4());
	if (iter != myvector.end()) {
		cout << "iter find in myvector at position: 【" << distance(myvector.begin(), iter) << "】." << endl;
		cout << "*iter = " << *iter<<endl;
	}
	return 0;
}

在这里插入图片描述

  
  (5) adjacent_find()
  adjacent_find() 函数用于在指定范围内查找 2 个连续相等的元素。该函数的语法格式为:

//查找 2 个连续相等的元素
ForwardIterator adjacent_find (ForwardIterator first, ForwardIterator last);
//查找 2 个连续满足 pred 规则的元素
ForwardIterator adjacent_find (ForwardIterator first, ForwardIterator last,
                               BinaryPredicate pred);

  其中,first 和 last 都为正向迭代器,其组合 [first, last] 用于指定该函数的查找范围;
  pred 用于接收一个包含 2 个参数且返回值类型为 bool 的函数,以实现自定义查找规则。

  
  关于adjacent_find()案例如下:

#include <iostream>     // std::cout
#include <algorithm>    // std::adjacent_find
#include <vector>       // std::vector
using namespace std;


//===========查找4---adjacent_find=====================
//以创建普通函数的形式定义一个查找规则
bool mycomp5(int i, int j) {
	return (i == j);
}
//以函数对象的形式定义一个查找规则
class mycomp6 {
public:
	bool operator()(const int& _Left, const int& _Right) {
		return (_Left == _Right);
	}
};
int main() {
	std::vector<int> myvector{ 5,20,5,30,30,20,10,10,20 };
	//调用第一种语法格式
	std::vector<int>::iterator it = adjacent_find(myvector.begin(), myvector.end());
	if (it != myvector.end()) {
		cout << "Position of two consecutive equal elements:【" << distance(myvector.begin(), it) << "】." << endl;
		cout << "one : " << *it << '\n';
	}

	//===============================
	//打印匹配范围
	cout << "===================" << endl;
	vector<int> v1(myvector.begin() + distance(myvector.begin(), it), myvector.end());
	cout << " 查找范围为:" << endl;
	for (int i = 0; i < v1.size(); i++)cout << v1[i] << " ";
	cout << endl;
	//调用第二种格式,++it 从上个找到的it位置开始,继续寻找是否有连续 2 个符合 mycomp2 规则的元素,也可以使用 mycomp1
	std::vector<int>::iterator it1 = adjacent_find(++it, myvector.end(), mycomp6());
	if (it1 != myvector.end()) {
		
		cout << "Position of two consecutive equal elements in myvector :【" << distance(myvector.begin(), it1) << "】." << endl;
		cout << "two : " << *it1<<endl;
	}
	return 0;
}

在这里插入图片描述

  

2.1.3 比较算法(2个)

  (1) equal()
  equal():可以用和比较字符串类似的方式来比较序列。如果两个序列的长度相同,并且对应元素都相等,equal() 算法会返回 true。有 4 个版本的 equal() 算法,其中两个用 == 运算符来比较元素,另外两个用我们提供的作为参数的函数对象来比较元素,所有指定序列的迭代器都必须至少是输入迭代器。

  用 == 运算符来比较两个序列的第一个版本期望 3 个输入迭代器参数,前两个参数是第一个序列的开始和结束迭代器,第三个参数是第二个序列的开始迭代器。如果第二个序列中包含的元素少于第一个序列,结果是未定义的。
  用 == 运算符的第二个版本期望 4 个参数:第一个序列的开始和结束迭代器,第二个序列的开始和结束迭代器,如果两个序列的长度不同,那么结果总是为 false。本节会演示这两个版本,但推荐使用接受 4 个参数的版本,因为它不会产生未定义的行为。

  
  关于 equal()案例如下:

// Using the equal() algorithm
#include <iostream>                                      // For standard streams
#include <vector>                                        // For vector container
#include <algorithm>                                     // For equal() algorithm
#include <iterator>                                      // For stream iterators
#include <string>                                        // For string class
using std::string;

int main()
{
    std::vector<string> words1 {"one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
    std::vector<string> words2 {"two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"};
    auto iter1 = std::begin(words1);
    auto end_iter1 = std::end(words1);
    auto iter2 = std::begin(words2);
    auto end_iter2 = std::end(words2);

    std::cout << "Container - words1:";
    std::copy(iter1, end_iter1, std::ostream_iterator<string>{std::cout, " "});
    std::cout << "\nContainer - words2:";
    std::copy(iter2, end_iter2, std::ostream_iterator<string>{std::cout, " "});
    std::cout << std::endl;

    std::cout << "\n1. Compare from words1[1] to end with words2:";
    std::cout << std::boolalpha << std::equal(iter1 + 1, end_iter1, iter2) << std::endl;

    std::cout << "2. Compare from words2[0] to second-to-last with words1:";
    std::cout << std::boolalpha << std::equal(iter2, end_iter2 - 1, iter1) << std::endl;

    std::cout << "3. Compare from words1[1] to words1[5] with words2:";
    std::cout << std::boolalpha << std::equal(iter1 + 1, iter1 + 6, iter2) << std::endl;
   
    std::cout << "4. Compare first 6 from words1 with first 6 in words2:";
    std::cout << std::boolalpha << std::equal(iter1, iter1 + 6, iter2, iter2 + 6) << std::endl;

    std::cout << "5. Compare all words1 with words2:";
    std::cout << std::boolalpha << std::equal(iter1, end_iter1, iter2) << std::endl;

    std::cout << "6. Compare all of words1 with all of words2:";
    std::cout << std::boolalpha << std::equal(iter1, end_iter1, iter2, end_iter2) << std::endl;

    std::cout << "7. Compare from words1[1] to end with words2 from first to second-to-last:";
    std::cout << std::boolalpha << std::equal(iter1 + 1, end_iter1, iter2, end_iter2 - 1) << std::endl;
}

在这里插入图片描述
  在这个案例中,对来自于 words1 和 words2 容器的元素的不同序列进行了比较。equal() 调用产生这些输出的原因如下:
    第 1 条语句的输出为 true,因为 words1 的第二个元素到最后一个元素都从 words2 的第一个元素开始匹配。第二个序列的元素个数比第一个序列的元素个数多 1,但 第一个序列的元素个数决定了比较多少个对应的元素。
    第 2 条语句的输出为 false,因为有直接的不匹配;words2 和 words1 的第一个元素不同。
    第 3 条语句的输出为 true,因为 word1 中从第二个元素开始的 5 个元素和 words2 的前五个元素相等。
    在第 4 条语句中,words2 的元素序列是由开始和结束迭代器指定的。序列长度相同,但它们的第一个元素不同,所以结果为 false。
    在第 5 条语句中,两个序列的第一个元素直接就不匹配,所以结果为 false。
    第 6 条语句的输出为 false,因为序列是不同的。这条语句不同于前面的 equal() 调用,因为指定了第二个序列的结束迭代器。
    第 7 条语句会从 words1 的第二个元素开始,与 word2 从第一个元素开始比较相同个数的元素,所以输出为 true。

  当用 equal() 从开始迭代器开始比较两个序列时,第二个序列用来和第一个序列比较的元素个数由第一个序列的长度决定。就算第二个序列比第一个序列的元素多,equal() 仍然会返回 true。如果为两个序列提供了开始和结束迭代器,为了使结果为 true,序列必须是相同的长度。

  
  (2) mismatch()
  equal() 可以告诉我们两个序列是否匹配。mismatch() 也可以告诉我们两个序列是否匹配,而且如果不匹配,它还能告诉我们不匹配的位置。

  mismatch() 的 4 个版本和 equal() 一样有相同的参数——第二个序列有或没有结束迭代器,有或没有定义比较的额外的函数对象参数。mismatch() 返回的 pair 对象包含两个迭代器。它的 first 成员是一个来自前两个参数所指定序列的迭代器,second 是来自于第二个序列的迭代器。当序列不匹配时,pair 包含的迭代器指向第一对不匹配的元素;因此这个 pair 对象为 pair<iter1+n,iter2 + n>,这两个序列中索引为 n 的元素是第一个不匹配的元素。

  当序列匹配时,pair 的成员取决于使用的 mismatch() 的版本和具体情况。iter1 和 end_iter1 表示定义第一个序列的迭代器,iter2 和 end_iter2 表示第二个序列的开始和结束迭代器。返回的匹配序列的 pair 的内容如下:

  (1) 对于 mismatch(iter1,end_iter1,iter2):
    返回 pair<end_iter1,(iter2 + (end_ter1 - iter1))>,pair 的成员 second 等于 iter2 加上第一个序列的长度。如果第二个序列比第一个序列短,结果是未定义的。

  (2) 对于 mismatch(iterl, end_iter1, iter2, end_iter2):
    当第一个序列比第二个序列长时,返回 pair<end_iter1, (iter2 + (end_iter1 - iter1))>,所以成员 second 为 iter2 加上第一个序列的长度。
    当第二个序列比第一个序列长时,返回 pair<(iter1 + (end_iter2 - iter2)),end_iter2>, 所以成员 first 等于 iter1 加上第二个序列的长度。
    当序列的长度相等时,返回 pair<end_iter1, end_iter2>。

  不管是否添加一个用于比较的函数对象作为参数,上面的情况都同样适用。

  
  关于 mismatch()案例如下:


// Using the equal() algorithm
#include <iostream>                                      // For standard streams
#include <vector>                                        // For vector container
#include <algorithm>                                     // For equal() algorithm
#include <iterator>                                      // For stream iterators
#include <string>                                        // For string class
using std::string;
int mainequal()
{
	std::vector<string> words1{ "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };
	std::vector<string> words2{ "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" };
	auto iter1 = std::begin(words1);
	auto end_iter1 = std::end(words1);
	auto iter2 = std::begin(words2);
	auto end_iter2 = std::end(words2);
	std::cout << "Container - words1:";
	std::copy(iter1, end_iter1, std::ostream_iterator<string>{std::cout, " "});
	std::cout << "\nContainer - words2:";
	std::copy(iter2, end_iter2, std::ostream_iterator<string>{std::cout, " "});
	std::cout << std::endl;
	std::cout << "\n1. Compare from words1[1] to end with words2:";
	std::cout << std::boolalpha << std::equal(iter1 + 1, end_iter1, iter2) << std::endl;
	std::cout << "2. Compare from words2[0] to second-to-last with words1:";
	std::cout << std::boolalpha << std::equal(iter2, end_iter2 - 1, iter1) << std::endl;
	std::cout << "3. Compare from words1[1] to words1[5] with words2:";
	std::cout << std::boolalpha << std::equal(iter1 + 1, iter1 + 6, iter2) << std::endl;

	std::cout << "4. Compare first 6 from words1 with first 6 in words2:";
	std::cout << std::boolalpha << std::equal(iter1, iter1 + 6, iter2, iter2 + 6) << std::endl;
	std::cout << "5. Compare all words1 with words2:";
	std::cout << std::boolalpha << std::equal(iter1, end_iter1, iter2) << std::endl;
	std::cout << "6. Compare all of words1 with all of words2:";
	std::cout << std::boolalpha << std::equal(iter1, end_iter1, iter2, end_iter2) << std::endl;
	std::cout << "7. Compare from words1[1] to end with words2 from first to second-to-last:";
	std::cout << std::boolalpha << std::equal(iter1 + 1, end_iter1, iter2, end_iter2 - 1) << std::endl;

	return 0;
}

在这里插入图片描述
  注意 words2 中的内容和前面示例中的有些不同。每一次应用 mismatch() 的结果都是由定义为 print_match 的 lambda 表达式生成的。它的参数是一个 pair 对象和一个 vector 容器的迭代器。使用 using 指令生成 word_iter 别名可以使 lambda 表达式的定义更简单。

  在 main() 的代码中使用了不同版本的 mismatch(),它们都没有包含比较函数对象的参数。如果第二个序列只用开始迭代器指定,为了和第一个序列匹配,它只需要有和第一个序列相等长度的元素,但也可以更长。如果第二个序列是完全指定的,会由最短的序列来确定比较多少个元素。


3、总结

  最后,长话短说,大家看完就好好动手实践一下,切记不能三分钟热度、三天打鱼,两天晒网。大家也可以自己尝试写写博客,来记录大家平时学习的进度,可以和网上众多学者一起交流、探讨,我也会及时更新,来督促自己学习进度。一开始提及的博主【AI菌】,个人已关注,并订阅了相关专栏(对我有帮助的),希望大家觉得不错的可以点赞、关注、收藏。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/12536.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

每个程序员都要知道的一个网站

在日常开发过程中&#xff0c;你是不是经常回到搜索引擎&#xff0c;搜索某个功能的实现方式&#xff0c;比如&#xff1a;Javascript 数组排序、正则表达式等等。 今天给大家推荐的这个网站&#xff0c;就可以满足大家的需求&#xff0c;它叫&#xff1a;30secondsofcode&…

抽象类与接口

目录 1. 抽象类 1.1 抽象类概念 1. 2&#x1f414;抽象类特性 1.3 抽象类的作用 2. 接口 2.1 接口是什么 2.2 语法规则 2.3 方法的使用 2.4 接口特性 2.5 实现接口 VS 继承类 2.6 抽象类 VS 接口&#xff08;总结&#xff09; 2.6 接口间的继承 &#x1f413; 随着…

漫画脸头像怎么制作?这几种方法可以帮到你

你们会经常更换头像吗&#xff1f;我身边就有一些朋友会这样做&#xff0c;看到喜欢的头像就换&#xff0c;而且他基本上都是找那些漫画脸来当头像。那如果我们把自己的人像制作成漫画脸&#xff0c;就不容易跟别人撞头像了&#xff0c;还显得有个性。 估计有很多小伙伴不知道漫…

NXP BootLoader源码分析并改写SD卡启动

1 官方资料 NXP官方提供了MCUBoot SDK&#xff1a;NXP_Kinetis_Bootloader_2.0.0 package&#xff0c;里面包含了各种型号芯片的的BootLoader。 BootLoader参考手册&#xff1a;doc/Kinetis Bootloader v2.0.0 Reference Manual.pdf上位机程序参考手册&#xff1a;Kinetis Fl…

疯狂小杨哥被王海打假

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; 知名打假人王海 发布视频&#xff0c;说疯狂小杨哥三只羊直播间售卖的金正破壁机和绞肉机虚标功率。破壁机标注功率为300W&#xff0c;实际为105W&#xff0c;绞肉机标注功率300W&#xff0c;实际功…

[附源码]java毕业设计咖啡销售管理系统-

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

总线仲裁的方式

总线仲裁的基本概念 同一时刻只能有一个设备控制总线传输操作&#xff0c;可以有一个或多个设备从总线接收数据。 将总线上所连接的各类设备按其对总线有无控制功能分为&#xff1a; 主设备&#xff1a;获得总线控制权的设备。 从设备&#xff1a;被主设备访问的设备&#xff0…

C++11标准模板(STL)- 算法(std::stable_partition)

定义于头文件 <algorithm> 算法库提供大量用途的函数&#xff08;例如查找、排序、计数、操作&#xff09;&#xff0c;它们在元素范围上操作。注意范围定义为 [first, last) &#xff0c;其中 last 指代要查询或修改的最后元素的后一个元素。 将元素分为两组&#xff0…

内网的基本构造

内网的基本构造 内网也就是常说的局域网(Local Area Network,简称LAN)&#xff0c;是由两个或两个以上相连的计算机组成&#xff0c;局域网是包含在较小区域内的网络&#xff0c;覆盖范围一般是方圆几千米之内&#xff0c;通常位于建筑物内。家庭WiFi网络和小型企业网络是常见…

一次GC暂停时间过长的排查与优化

告警 GC日志分析 日志 2022-11-17T14:28:40.3150800: 1956232.826: [GC (Allocation Failure) 2022-11-17T14:28:40.3150800: 1956232.826: [ParNew: 1576103K->2817K(1769472K), 0.0241066 secs] 4197176K->2624616K(5046272K), 0.0243910 secs] [Times: user0.04 sys…

nginx配置详解

nginx 是一个高性能的HTTP 和反向代理服务器,特点是占有内存少&#xff0c;并发能力强 用途&#xff1a; 可以作为静态页面的 web 服务器正向代理&#xff08;通过nginx代理 访问外部资源&#xff0c;比如fanqiang&#xff09;反向代理 &#xff08;隐藏真实服务器地址&…

创建vite项目

前提&#xff1a;Vite需要Node.js版本> 12.0.0 1. 创建文件夹&#xff0c;文件夹下打开cmd,输入 yarn create vite C:\Users\admin\Desktop\new>yarn create vite 2. 进行选择 3. vite.config.js 配置 &#xff08;注意按目录创建global.scss&#xff09; import …

关于射频测试电缆 这些知识你知道吗?

射频电缆组件的正确选择除了频率范围&#xff0c;驻波比&#xff0c;插入损耗等因素外&#xff0c;还应考虑电缆的机械特性&#xff0c;使用环境和应用要求&#xff0c;另外&#xff0c;成本也是一个永远不变的因素。以下带大家了解射频电缆相关知识。 射频电缆组件的基本选择原…

【附源码】Python计算机毕业设计网上宠物商店系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

Android 天气APP(三十六)运行到本地AS、更新项目版本依赖、去掉ButterKnife

运行到本地AS、更新项目版本依赖、去掉ButterKnife前言正文一、新版Android Studio编译运行① 升级项目gradle版本② 切换JDK版本③ BuildConfig报错二、百度的SDK使用① 开发版SHA1的作用是什么&#xff1f;② 什么时候需要更换开发版SHA1&#xff1f;③ 怎么获取开发版SHA1&a…

STM8S系列基于STVD开发,ADC不同精度采样示例

STM8S系列基于STVD开发&#xff0c;ADC不同精度采样示例&#x1f4cc;相关篇《STM8S系列基于STVD开发&#xff0c;自定义printf函数TIM5精确延时函数模块化工程示例》 ✨本工程以上面一篇的工程为模板&#xff0c;在此基础上实现ADC电压采样。 &#x1f3ac;&#x1f4fd;&…

java 读取resource下的文件

目录一、普通main代码里使用1.假设有如下结构的代码&#xff08;1&#xff09;、main方法里复制resource下的文件&#xff08;2&#xff09;、main方法里读取resource下的文件2.假设有如下结构的代码二、对于springboot项目读取resource下的资源文件一、普通main代码里使用 1.…

虚拟主播是什么,有什么技术原理?- 沉睡者IT

虚拟主播是什么&#xff1f;虚拟形象人物是通过人工智能技术的研究和积累&#xff0c;在克服了计算机图形学和AI核心技术的各个学科的智能化、平台化、虚拟人、虚拟内容在各个维度的技术难题后&#xff0c;提供给用户的核心资产。虚拟主播指的是在视频网站上使用虚拟图片进行投…

C. Bargain(数学贡献法)

Problem - 1422C - Codeforces 有时&#xff0c;要在讨价还价中达成协议并不容易。现在&#xff0c;萨沙和沃瓦就无法达成协议。萨沙说出了一个尽可能高的价格&#xff0c;然后沃瓦想从这个价格中删除尽可能多的数字。更详细地说&#xff0c;Sasha说出某个整数的价格n&#xff…

[R]第二节 练习一关于数值向量

1.产生一个等差数列(1,3,5,7,……,99)赋值给向量x x <- array(seq(from1, to99, by2)) seq函数解析 seq(from,to,length)该函数的意思是生成一组数字&#xff0c;从from开始&#xff0c;到to结束&#xff0c;每两个数间的间隔是length,如: seq(2,10,2),会生成一组数&…