頭歌 | 數據結構與算法課程設計-算法與競賽(第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 }
點擊查看代碼

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM