头歌 | 数据结构与算法课程设计-算法与竞赛(第3章) - C++与算法基础二

Algorithm 中文意思是算法,是一个计算的具体步骤,常用于数据处理、计算以及自动推理。它作为 C++ 标准模版库 STL 中最重要的头文件之一,其提供了大量非成员模版函数,例如排序操作、二分查找操作、集合操作以及堆操作等。同时可以通过迭代器或指针访问任何对象序列,例如 STL 容器数组或实例。更多的了解请参考官方文档

本实训主要设置了四个关卡:第一关和第二关介绍了 Algorithm 中的二分搜索操作 binary_search 及其相关搜索操作;第三关是修改序列操作 Modifying sequence operations ;第四关讲的是非修改序列操作 Non-modifying sequence operations 。最后在每个关卡都设置了实例,考察学员对所讲内容的理解和在线编程能力。

 

第1关:二分查找:在N个无序整数里面查找M个指定整数

 任务描述

本关任务:给定包含 N 个整数的无序序列 S(a1,a2,..,aN),以及 M 次查询序列 Q(b1,b2,..,bM),判定 bj​ 是否在序列 S 中。

相关知识

为了完成本关任务,你需要掌握:1.解题思路,2.快速排序算法,3.二分查找算法。

解题思路

本关卡问题清晰,解法简单:对于每次查询bj,在序列S中遍历ai是否等于bj。虽然该解法实现简单,但是执行效率低,运算复杂度高O(N×M)。

高效解法:首先运用快速排序算法,将无序序列变为有序(升序),然后对每次查找操作,使用二分查找算法判断元素是否存在。该解法实现稍微有点复杂,但是执行效率高,运算复杂度低O(N×logN+M×logN)。

快速排序算法

快速排序算法的背景和原理前面已有很多实训介绍过了,为了方便实现,一般使用 algorithm 中模板函数 sort ,请认真参考实训《算法与竞赛(第2章) - C++与Algorithm基础一》 的第三个关卡,之后的实训将不再对sort进行讲解。

二分查找算法

二分查找算法也称折半查找算法 Binary Search Algorithm ,它是一种效率较高的查找方法,复杂度为O(logN)。二分查找算法要求线性表(序列)必须采用顺序存储结构,而且表中元素按关键字有序排列。

核心思想:将表中间位置记录的关键字与待查找的关键字进行比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

幸运的是,C++ 在 Algorithm 算法模板中集成了二分查找算法,这样仅仅调用一个模板函数 binary_search 就可以实现指定元素(关键字)的查找了。其函数原型及其应用实例如下:

 1 \\ binary_search函数原型
 2 default (1):
 3     template <class ForwardIterator, class T>
 4     bool binary_search (ForwardIterator first, ForwardIterator last, const T& val);
 5 custom (2):
 6     template <class ForwardIterator, class T, class Compare>
 7     bool binary_search (ForwardIterator first, ForwardIterator last, const T& val, Compare comp);
 8 \\ binary_search应用实例
 9 int arr[4] = {1,2,3,4}; // 升序数组
10 bool judge1 = binary_search(arr, arr+4, 1); // judge1结果为true
11 bool judge2 = binary_search(arr, arr+4, 5); // judge2结果为false

本关卡使用的是整型数据,使用默认的模板函数即可。若有兴趣学习自定义数据类型下的二分查找,请参考实训《算法与竞赛(第2章) - C++与Algorithm基础一》第三个关卡对自定义数据类型的相关操作。

编程要求

本关的编程任务是补全右侧代码片段 main 中 Begin 至 End 中间的代码,具体要求如下:

在 main 中,读取N个无序序列,并存储在数组中,然后对无序数组进行排序,最后调用二分查找算法完成 次指定元素的查找任务,并输出查找结果。若在序列中,输出 bj in array,否则输出 bj not in array

测试说明

平台将自动编译补全后的代码,并生成若干组测试数据,接着根据程序的输出判断程序是否正确。

以下是平台的测试样例:

测试输入:

7

2 5 9 5 5 3 1

3

4 7 5

预期输出:

4 not in array

7 not in array

5 in array

 

输入格式:

第一行:序列元素个数N

第二行:N个无序序列元素

第三行:查询次数M

第四行:M个待查询元素

输出格式:

输出M行,每行对应查询结果,每行末尾换行!!!


开始你的任务吧,祝你成功!

 

 

 1 //
 2 //  main.cpp
 3 //  step1
 4 //
 5 //  Created by ljpc on 2018/7/8.
 6 //  Copyright ? 2018年 ljpc. All rights reserved.
 7 //
 8 
 9 #include <iostream>
10 #include <algorithm>
11 #include <cstdio>
12 
13 using namespace std;
14 
15 int main(int argc, const char * argv[]) 
16 {
17 
18     // 请在这里补充代码,完成本关任务
19     /********** Begin *********/
20     int n,m;
21     cin>>n;
22     int a[n+10];//需要注意的是,有的编译器支持这种定义方法,有的不支持
23     //可以考虑直接定义一个很大的数组 
24     //如果这样定义的话,顺序不能颠倒,只有有了n之后才可以定义这个数组 
25     
26     for(int i=1;i<=n;i++) cin>>a[i];//依次输入这n个无序序列并储存在数组中 
27     
28     sort(a,a+n+1);//利用sort函数对无序数组进行排序,sort默认使用 < 号 
29     
30     cin>>m;
31     int b[m+10];
32     for(int i=1;i<=m;i++)
33         cin>>b[i];
34         
35     for(int i=1;i<=m;i++){//利用for循环依次对数组中存储的每一个数在有序数组a中进行查找 
36         if(binary_search(a,a+n,b[i])) //binary_search函数题目中有写到,是对有序数组进行查找的 
37             cout<<b[i]<<" in array"<<endl;
38         else cout<<b[i]<<" not in array"<<endl;
39     }
40     /********** End **********/    
41     
42     return 0;
43 }
点击查看代码

 

 

 

第2关二分查找:在N个有序整数里面查找M个指定整数的闭区间位置

任务描述

本关任务:给定包含N个整数的升序序列S(a1,a2,..,aN),以及M次查询序列Q(b1,b2,..,bM),求bj在序列S中的闭区间位置(测试数据保证bj存在序列S中),例如2在升序序列 1,2,2,3 中的闭区间位置为 [1,2] 

相关知识

为了完成本关任务,你需要掌握:1.模板函数 lower_bound ,2.模板函数 upper_bound ,3.模板函数 equal_range 

模板函数 lower_bound

上个关卡介绍了 binary_search 的模板函数,实际上它的内部实现是基于 lower_bound 函数实现的,通过 lower_bound 在有序序列里查找不小于关键字的元素,并返回元素索引位置最低的地址,最后根据地址来判断是否查找成功,代码如下:

1 template <class ForwardIterator, class T>
2 bool binary_search (ForwardIterator first, ForwardIterator last, const T& val){
3      first = std::lower_bound(first,last,val);
4      return (first!=last && !(val<*first));
5     //first!=last为true:说明找到一个不小于关键字的元素
6     //!(val<*first) 为true:说明该元素与待查找关键字相等
7 }

模板函数 lower_bound 的基本用途是查找有序区间中第一个 大于或等于 某给定值的元素的位置,由此本关卡的任务可以利用 lower_bound 获取序列中等于待查找关键字的元素的位置。其函数原型及其应用实例如下:

 1 \\ 函数原型
 2 default (1):
 3     template <class ForwardIterator, class T>
 4     ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last, const T& val);
 5 custom (2):
 6     template <class ForwardIterator, class T, class Compare>
 7     ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last,const T& val, Compare comp);
 8 \\ 应用实例
 9 int arr[5] = {1,2,2,4,5};
10 int a = lower_bound(arr, arr+5, 2) - arr; // a结果为1

模板函数 upper_bound

模板函数 upper_bound 的基本用途与 lower_bound 相对,是查找有序区间中第一个 大于 某给定值的元素的位置,由此本关卡的任务可以利用 upper_bound 获取序列中第一个 大于 待查找关键字的元素的位置,往前移一位就是最后一个等于待查找关键字的元素的位置。其函数原型及其应用实例如下:

 1 \\ 函数原型
 2 default (1):
 3     template <class ForwardIterator, class T>
 4     ForwardIterator upper_bound (ForwardIterator first, ForwardIterator last, const T& val);
 5 custom (2):
 6     template <class ForwardIterator, class T, class Compare>
 7     ForwardIterator upper_bound (ForwardIterator first, ForwardIterator last, const T& val, Compare comp);
 8 \\ 应用实例
 9 int arr[5] = {1,2,2,4,5};
10 int b = upper_bound(arr, arr+5, 2) - arr; // b结果为3

模板函数 equal_range

模板函数 equal_range 综合了 lower_bound 和 upper_bound 的功能,通过内部调用这两个上下界查找函数,返回两个地址并组成 pair :第一个地址是序列中第一个大于等于待查找关键字的元素位置,而第二个地址是第一个大于待查找关键字的元素位置。因为本关卡的数据保证在序列中存在待查找关键字,所以 equal_range 返回的是一个左闭右开的区间位置。其函数原型及其应用实例如下:

1 default (1):
2     template <class ForwardIterator, class T>
3     pair<ForwardIterator,ForwardIterator>
4     equal_range (ForwardIterator first, ForwardIterator last, const T& val);
5 custom (2):
6     template <class ForwardIterator, class T, class Compare>
7     pair<ForwardIterator,ForwardIterator>
8     equal_range (ForwardIterator first, ForwardIterator last, const T& val, Compare comp);

模板函数 equal_range 基于 lower_bound 和 upper_bound 的函数内部实现如下:

 1 \\ 函数原型
 2 template <class ForwardIterator, class T>
 3 pair<ForwardIterator,ForwardIterator>
 4 equal_range (ForwardIterator first, ForwardIterator last, const T& val){
 5     ForwardIterator it = std::lower_bound (first,last,val);
 6     return std::make_pair ( it, std::upper_bound(it,last,val) );
 7 }
 8 \\ 应用实例
 9 int arr[5] = {1,2,2,4,5};
10 auto bounds = equal_range(arr, arr+5, 2);
11 int a = bounds.first-arr; // a结果为1
12 int b = bounds.second-arr; // b结果为3

编程要求

本关的编程任务是补全右侧代码片段 main 中 Begin 至 End 中间的代码,具体要求如下:

在 main 中,读取 N 个升序序列,并存储在数组中,基于 lower_bound 和 upper_bound 算法(或 equal_range )完成M次指定元素的查找任务,并输出查找闭区间结果(输出格式严格遵循样例)。

测试说明

平台将自动编译补全后的代码,并生成若干组测试数据,接着根据程序的输出判断程序是否正确。

以下是平台的测试样例:

测试输入:

7

1 1 2 3 5 5 6

2

5 6

预期输出:

5 at order array position [4,5]

6 at order array position [6,6]

 

输入格式:

第一行:序列元素个数N

第二行:N个升序序列元素

第三行:查询次数M

第四行:M个待查询元素

输出格式:

输出M行,每行对应查询结果,每行末尾换行!!!


开始你的任务吧,祝你成功!

 1 //
 2 //  main.cpp
 3 //  step2
 4 //
 5 //  Created by ljpc on 2018/7/8.
 6 //  Copyright ? 2018年 ljpc. All rights reserved.
 7 //
 8 
 9 #include <iostream>
10 #include <algorithm>
11 #include <cstdio>
12 using namespace std;
13 
14 int main(int argc, const char * argv[]) 
15 {
16    
17     // 请在这里补充代码,完成本关任务
18     /********** Begin *********/
19     int n;
20     cin>>n;//获取有序序列的元素个数,便于利用循环输入序列 
21     int a[n+10];//定义一个数组用于存储序列 
22     for(int i=0;i<=n-1;i++){//利用for循环不断输入序列 
23         //要注意一下这里,需要从数组的第一个位置开始记录
24         cin>>a[i]; 
25     } 
26     
27     int m;
28     cin>>m;//获取要在有序序列中的查询次数 
29     int b[m+10];//定义数组b用于存储待查找元素 
30     for(int i=0;i<=m-1;i++){
31         //要注意一下这里,需要从数组的第一个位置开始记录 
32         cin>>b[i];
33         
34     } 
35     for(int i=0;i<=m-1;i++){
36         auto bounds = equal_range(a,a+n,b[i]);
37         //利用函数equal_range查询 
38         int j=bounds.first-a;//序列中第一个【大于等于】待查找关键字的元素位置 
39         int p=bounds.second-a;//序列中第一个【大于】待查找关键字的元素位置 
40         cout<<b[i]<<" at order array position ["<<j<<","<<p-1<<"]"<<endl;
41         //因为p是大于的位置,而我们要求的是闭区间,所以应该减去 1 
42     } 
点击查看代码

 

如果因为个人习惯问题,喜欢将for循环中的i从1开始记录的话,代码应该这么写:

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 using namespace std;
 5 
 6 int main(int argc, const char * argv[]) 
 7 {
 8    
 9     // 请在这里补充代码,完成本关任务
10     /********** Begin *********/
11     int n;
12     cin>>n;//获取有序序列的元素个数,便于利用循环输入序列 
13     int a[n+10];//定义一个数组用于存储序列 
14     for(int i=1;i<=n;i++){//利用for循环不断输入序列 
15         cin>>a[i]; 
16     } 
17     
18     int m;
19     cin>>m;//获取要在有序序列中的查询次数 
20     int b[m+10];//定义数组b用于存储待查找元素 
21     for(int i=1;i<=m;i++){
22         //要注意一下这里,需要从数组的第一个位置开始记录 
23         cin>>b[i];
24         
25     } 
26     for(int i=1;i<=m1;i++){
27         auto bounds = equal_range(a+1,a+n+1,b[i]);
28         //利用函数equal_range查询 
29         int j=bounds.first-a;//序列中第一个【大于等于】待查找关键字的元素位置 
30         int p=bounds.second-a;//序列中第一个【大于】待查找关键字的元素位置 
31         cout<<b[i]<<" at order array position ["<<j<<","<<p-1<<"]"<<endl;
32         //此时,j和 p所代表的地址实际上比要查找的关键字的地址还要大于 1,所以应该都减 1 
33         //又因为p是大于的位置,而我们要求的是闭区间,所以应该减去 2 
34     } 
35 
36 
37     /********** End **********/
38  
39     return 0;
40 }
点击查看代码

 

 

第3关修改序列(数组)操作的应用

任务描述

本关任务:编写一个程序,实现复制Copy_N,交换Swap,取代Replace,填充Fill,倒置Reverse,滚动Rotate等修改序列操作。

相关知识

为了完成本关任务,你需要掌握:1.复制Copy_N,2.交换Swap,3.取代Replace,4.填充Fill,5.倒置Reverse,6.滚动Rotate

复制Copy_N

Algorithm中有两个常用的复制函数:copycopy_n,其中copy复制整个数组到新的数组中,而copy_n则是可选择的复制前n个元素到新的数组。 copy函数原型及其应用实例如下,参数first为数组首地址,参数last为数组尾地址,参数result为新数组首地址:

1 \\ 函数原型
2 template <class InputIterator, class OutputIterator>
3 OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result);
4 \\ 应用实例
5 int arr1[4] = {1,3,2,4};
6 int arr2[4];
7 copy(arr1, arr1+4, arr2);
8 \\或者 arr2 =  copy(arr1, arr1+4, arr2);

copy_n函数原型及其应用实例如下,参数first为数组首地址,参数n为要复制的数组元素个数,参数result为新数组首地址:

1 \\ 函数原型
2 template <class InputIterator, class Size, class OutputIterator>
3 OutputIterator copy_n (InputIterator first, Size n, OutputIterator result);
4 \\ 应用实例
5 int arr1[4] = {1,3,2,4};
6 int arr2[4];
7 copy_n(arr1, 4, arr2);

交换Swap

Algorithm中交换模板函数为swap,传入两个参数地址引用,功能是交换这两个参数的数值,其函数原型及其应用实例如下:

1 \\ 函数原型
2 template <class T> void swap (T& a, T& b)
3 \\ 应用实例
4 int a=1, b=2;
5 swap(a, b);
6 \\ a结果为2,b结果为1

取代Replace

Algorithm中取代模板函数为replace,传入参数first为数组首地址,参数last为数组尾地址,要被替换的旧元素为参数old_value,替换的新的元素为参数new_value,函数功能是将数组中所有的old_value替换为new_value,其函数原型及其应用实例如下:

1 \\ 函数原型
2 template <class ForwardIterator, class T>
3 void replace (ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value);
4 \\ 应用实例
5 int arr[4] = {1,2,2,3};
6 replace(arr, arr+4, 2, 0);
7 \\ arr结果为{1,0,0,3}

填充Fill

Algorithm中填充模板函数为fill,传入参数first为数组首地址,参数last为数组尾地址,填充值为参数val,函数功能是将数组中的所有元素都重新赋值为val,其函数原型及其应用实例如下:

1 \\ 函数原型
2 template <class ForwardIterator, class T>
3 void fill (ForwardIterator first, ForwardIterator last, const T& val);
4 \\ 应用实例
5 int arr[4] = {1,2,2,3};
6 fill(arr, arr+4, 5);
7 \\ arr结果为{5,5,5,5}

特别的,类似的填充函数还有memset,在头文件string.h中,但是赋值有限,一般仅限于-10,若设置为其他数值,则实际结果有误。

倒置Reverse

Algorithm中倒置模板函数为reverse,传入参数first为数组首地址,参数last为数组尾地址,函数功能是将数组中的所有元素对称交换,例如比如1 2 3,变为3 2 1,其函数原型及其应用实例如下:

1 \\ 函数原型
2 template <class BidirectionalIterator>
3 void reverse (BidirectionalIterator first, BidirectionalIterator last);
4 \\ 应用实例
5 int arr[4] = {1,2,3,4};
6 reverse(arr, arr+4);
7 \\ arr结果为{4,3,2,1}

滚动Rotate

Algorithm中滚动模板函数为rotate,传入参数first为数组首地址,参数last为数组尾地址,而参数middle则是数组中要滚动的最后一个元素的后一个地址,滚动完成后该地址将成为首地址,比如数组arr=[0,1,2,3,4],相应的参数为first=arrlast=arr+5middle=arr+3,则滚动后的结果为3 4 0 1 2,其函数原型及其应用实例如下:

1 \\ 函数原型
2 template <class ForwardIterator>
3 ForwardIterator rotate (ForwardIterator first, ForwardIterator middle, ForwardIterator last);
4 \\ 应用实例
5 int arr[5] = {0,1,2,3,4};
6 rotate(arr, arr+3, arr+5);
7 \\ arr结果为{3,4,0,1,2}

编程要求

本关的编程任务是补全右侧代码片段Copy_NSwapReverseReplaceFill,和RotateBeginEnd中间的代码,具体要求如下:

  • Copy_N中,复制数组arr中前n个元素到一个新的数组,并将新数组作为函数返回值。
  • Swap中,实现整数x和整数y数值交换,因为传入的参数为地址引用,所以对xy的修改都是真实有效的修改,也就是说会改变原来的值。
  • Reverse中,实现数组arr所有元素首尾倒置,即交换arr[0]arr[n-1]arr[1]arr[n-2],以此类推。
  • Replace中,将数组arr中所有的元素x都替换为新的元素y
  • Fill中,实现数组arr的填充,将所有的元素赋值为元素z
  • Rotate中,实现m次数组arr左向滚动,即每次数组滚动将arr[0]移动到数组末尾,然后元素依次往前移动一位。

以上所有功能学员可以基于Algorithm模板库调用相应的模板函数来实现,也可以自己编写具体代码来实现,进一步理解其原理和作用。

测试说明

平台将自动编译补全后的代码,并随机生成若干组测试数据,接着根据程序的输出判断程序是否正确(学员不需要关注测试用例,只需实现上述的编程要求即可)。


开始你的任务吧,祝你成功!

 

 1 //
 2 //  code.cpp
 3 //  step3
 4 //
 5 //  Created by ljpc on 2018/7/12.
 6 //  Copyright ? 2018年 ljpc. All rights reserved.
 7 //
 8 
 9 #include "code.h"
10 
11 int* Copy_N(int *arr, int n)
12 // 函数功能:复制数组arr中前n个元素并作为函数返回值
13 {
14     // 请在这里补充代码,完成本关任务
15     /********** Begin *********/
16     int *arr2 = new int[n];
17     for(int  i=0;i<n;i++){
18         arr2[i]=arr[i];
19     }
20     return arr2;
21     /********** End **********/
22 }
23 
24 void Swap(int &a, int &b)
25 // 函数功能:交换参数x和参数y
26 {
27     // 请在这里补充代码,完成本关任务
28     /********** Begin *********/
29     swap(a,b);
30 
31     /********** End **********/
32 }
33 
34 void Replace(int *arr, int n, int x, int y)
35 // 函数功能:在数组arr中将元素x替换为y,其中n为数组个数
36 {
37     // 请在这里补充代码,完成本关任务
38     /********** Begin *********/
39     replace(arr,arr+n,x,y);
40 
41     /********** End **********/
42 }
43 
44 void Fill(int *arr, int n, int z)
45 // 函数功能:将大小为n的数组的所有元素填充为元素z
46 {
47     // 请在这里补充代码,完成本关任务
48     /********** Begin *********/
49     fill(arr,arr+n,z);
50 
51     /********** End **********/
52 }
53 
54 void Reverse(int *arr, int n)
55 // 函数功能:倒置数组arr的元素,比如1 2 3,变为3 2 1,其中n为数组个数
56 {
57     // 请在这里补充代码,完成本关任务
58     /********** Begin *********/
59     reverse(arr,arr+n);
60 
61     /********** End **********/
62 }
63 
64 void Rotate(int *arr, int n, int m)
65 // 函数功能:向左边滚动m个元素,并补到数组右边,比如 1 2 3 4,滚动m=2个元素,结果为3 4 1 2,其中n=4是数组个数
66 {
67     // 请在这里补充代码,完成本关任务
68     /********** Begin *********/
69     rotate(arr,arr+m,arr+n);
70 
71     /********** End **********/
72 }
点击查看代码

 

 

 

第4关:非修改序列(数组)操作的应用

任务描述

本关任务:编写一个程序,实现无序数组查找指定元素Find,无序数组查找指定数组子序列Find_End,指定元素个数统计Count,两个数组相等比较Equal等非修改序列操作。

相关知识

为了完成本关任务,你需要掌握:1.无序数组查找指定元素Find,2.无序数组查找指定数组子序列Find_End,3.指定元素个数统计Count,4.两个数组相等比较Equal

无序数组查找指定元素Find

与上个实训介绍的二分查找binary_search不一样,Algorithm中的模板函数find可以在无序数组中的查找指定元素x,若存在则返回第一个x所在的地址,否则返回数组尾地址,其函数原型及其应用实例如下,其中传入参数first为数组首地址,参数last为数组尾地址,待查找指定元素为参数val

1 \\ 函数原型
2 template <class InputIterator, class T>
3 InputIterator find (InputIterator first, InputIterator last, const T& val);
4 \\ 应用实例
5 int arr[4] = {1,3,2,3};
6 int *p = find(arr, arr+4, 3); // p结果为地址arr+1
7 int *q = find(arr, arr+4, 0); // q结果为地址arr+4

无序数组查找指定数组子序列Find_End

Algorithm中的模板函数find_end可以在无序数组arr1中的查找指定子数组arr2是否存在,若存在则返回待查子数组arr2最后出现在原数组arr1的地址,否则返回原数组的尾地址,例如arr1=[0,3,4,3,4]arr2=[3,4],返回结果为arr1+3,其函数原型及其应用实例如下:

1 \\ 函数原型
2 template <class ForwardIterator1, class ForwardIterator2>
3 ForwardIterator1 find_end (ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2);
4 \\ 应用实例
5 int arr[5] = {0,3,4,3,4};
6 int arr1[2] = {3,4};
7 int arr2[2] = {3,5};
8 int *p = find_end(arr, arr+5, arr1, arr1+2); // p结果为地址arr+3
9 int *q = find_end(arr, arr+5, arr2, arr2+2); // q结果为地址arr+5

特别的,如想要第一次出现的地址,模板函数search 可以实现这一功能,使用方式同上,其函数原型如下:

1 template <class ForwardIterator1, class ForwardIterator2>
2 ForwardIterator1 search (ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2);

指定元素个数统计Count

Algorithm中的模板函数count可以在数组中统计指定元素x出现的次数,传入参数first为数组首地址,参数last为数组尾地址,参数x为待统计的指定元素,其函数原型及其应用实例如下:

1 \\ 函数原型
2 template <class InputIterator, class T>
3 typename iterator_traits<InputIterator>::difference_type count (InputIterator first, InputIterator last, const T& val);
4 \\ 应用实例
5 int arr[5] = {0,3,4,3,4};
6 int cnt = count(arr, arr+5,3); // cnt结果为2

两个数组相等比较Equal

两个数组相等意思是数组个数相同,对应位置上的元素值也相同,Algorithm中的模板函数equal就可以比较两个数组是否相等,返回比较真值,其函数原型及其应用实例如下,其中参数first1是第一个数组的首地址,参数last1是第一个数组的尾地址,参数first2是第二个参数的首地址,默认两个数组元素个数是相同的,否则没有比较意义:

1 \\ 函数原型
2 template <class InputIterator1, class InputIterator2>
3 bool equal (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2);
4 \\ 应用实例
5 int arr1[2] = {3,4};
6 int arr2[2] = {3,4};
7 int arr3[2] = {3,5};
8 bool judge1 = equal(arr1, arr1+2, arr2); // judge1结果为地址true
9 bool judge2 = equal(arr1, arr1+2, arr3); // judge2结果为地址false

编程要求

本关的编程任务是补全右侧代码片段FindFind_EndCountEqualBeginEnd中间的代码,具体要求如下:

  • Find中,对于给定的数组首地址和尾地址,查找元素x是否在数组中,若在则返回第一个x所在的地址,否则返回数组尾地址。
  • Find_End中,对于给定数组arr1及其个数n1,数组arr2及其个数n2,查找数组arr2是否在arr1中,若数组arr2在数组arr1中出现,则返回数组arr2[0]arr1中最后一次出现的地址,否则,返回数组arr1尾地址,即arr1+n1
  • Count中,统计指定元素x在数组中出现的次数。
  • Equal中,对于给定数组arr1及其个数n1,数组arr2,比较两个数组是否相等,若相等则返回true,否则返回false

以上所有功能学员可以基于Algorithm模板库调用相应的模板函数来实现,也可以自己编写具体代码来实现,进一步理解其原理和作用。

测试说明

平台将自动编译补全后的代码,并随机生成若干组测试数据,接着根据程序的输出判断程序是否正确(学员不需要关注测试用例,只需实现上述的编程要求即可)。


开始你的任务吧,祝你成功!

 

 1 //
 2 //  code.cpp
 3 //  step4
 4 //
 5 //  Created by ljpc on 2018/7/14.
 6 //  Copyright © 2018年 ljpc. All rights reserved.
 7 //
 8 
 9 #include "code.h"
10 
11 int* Find(int *first, int *last, int x)
12 // 函数功能:给定数组首地址和尾地址,若x在数组中,返回第一个x所在的地址,否则返回尾地址
13 {
14     // 请在这里补充代码,完成本关任务
15     /********** Begin *********/
16     //int static *q = find(*first,*last,x);
17     return find(first,last,x);
18     /********** End **********/
19 }
20 
21 int* Find_End(int *arr1, int n1, int *arr2, int n2)
22 // 函数功能:给定数组arr1,个数n1,数组arr2,个数n2,
23 //         若数组arr2在数组arr1中出现(连续),则返回数组arr2[0]在arr1中最后一次出现的地址
24 //         否则,返回数组arr1尾地址,即arr1+n1
25 {
26     // 请在这里补充代码,完成本关任务
27     /********** Begin *********/
28     int *q=find_end(arr1,arr1+n1,arr2,arr2+n2);
29     return q;
30     /********** End **********/
31 }
32 
33 int Count(int *first, int *last, int x)
34 // 函数功能:给定数组首地址和尾地址,统计数组中元素x的个数,并返回
35 {
36     // 请在这里补充代码,完成本关任务
37     /********** Begin *********/
38     return count(first,last,x);
39     /********** End **********/
40 }
41 
42 bool Equal(int *arr1, int n1, int *arr2)
43 // 函数功能:给定数组arr1,个数n1,数组arr2,(两个数组个数相同),判断两个数组是否相等
44 {
45     // 请在这里补充代码,完成本关任务
46     /********** Begin *********/
47     bool a;
48     for(int i=0;i<n1;i++){
49         if(arr1[i]==arr2[i])a=true;
50         else {
51             a=false;
52             break;
53         }
54     }
55     return a;
56     /********** End **********/
57 }
点击查看代码

 

posted @ 2021-09-28 23:25  ◆◇dear丶妖孽╮ゞ  阅读(3575)  评论(0编辑  收藏  举报
……
芋、头、sleepwalking、…