頭歌 | 數據結構與算法課程設計-算法與競賽(第2章) - C++與算法基礎一


Algorithm中文意思是算法,是一個計算的具體步驟,常用於數據處理、計算以及自動推理。它作為C++標准模版庫STL中最重要的頭文件之一,其提供了大量非成員模版函數,例如排序操作、二分查找操作、集合操作以及堆操作等。同時可以通過迭代器或指針訪問的任何對象序列,例如STL容器數組或實例。

本實訓主要設置了三個關卡:第一關介紹了Algorithm中的Min/Max操作;第二關是自定義數據類型結構體下的Min函數應用;第三關講的是C++模板中的快速排序算法。最后在每個關卡都設置了實例,考察學員對所講內容的理解和在線編程能力。

 

第1關:Algorithm模板中的Min/Max應用

任務描述

本關任務:基於Algorithm中的模板函數Min/Max編寫一個程序:在整型、浮點型、字符類型、字符串類型中,計算出兩個相同類型數據間的最小值和最大值。

相關知識

為了完成本關任務,你需要掌握:1.Algorithm模板函數min,2.Algorithm模板函數max,3.Algorithm模板函數minmax

Algorithm 模板函數 min

Algorithm模板函數中,關於min的用法主要有兩個:基礎數據類型的最小值函數和自定義數據類型的最小值函數。基礎數據類型指整型int,單精度浮點型float,雙精度浮點型double,字符類型char,字符串指針類型char*,字符串對象類型string等數據類型,而自定義的數據類型通常為結構體數據類型。其函數原型如下:

1 default (1): // 默認的基礎數據類型最小值函數
2     template <class T> const T& min (const T& a, const T& b);
3 custom (2): // 自定義的數據類型最小值函數
4     template <class T, class Compare>
5     const T& min (const T& a, const T& b, Compare comp);

在本關卡中,主要是介紹默認的基礎類型最小值函數及其實戰,有關自定義數據類型的最小值函數的詳細介紹和實戰將在下一個關卡給出。使用示例如下:

1 #include <algorithm>        // algorithm頭文件
2 int a=1, b=2;
3 int c = std::min(a, b);        // 調用min函數方式一
4 using namespace std;        // or 調用min函數方式二
5 int d = min(a, b);

Algorithm 模板函數 max

最大值函數與最小值函數類似,使用方法也是一樣的,也包含兩個主要的用法。其函數原型如下:

1 default (1):
2     template <class T> const T& max (const T& a, const T& b);
3 custom (2):
4     template <class T, class Compare>
5     const T& max (const T& a, const T& b, Compare comp);

Algorithm 模板函數 minmax

特別的,在Algorithm模板函數中還包含一個特殊的函數:最小值最大值函數,它以數據對pair的形式返回兩個值:最小值和最大值。同樣的,該函數也能處理基礎數據類型和自定義數據類型,其函數原型如下:

1 default (1):
2     template <class T>
3     pair <const T&,const T&> minmax (const T& a, const T& b);
4 custom (2):
5     template <class T, class Compare>
6     pair <const T&,const T&> minmax (const T& a, const T& b, Compare comp);

因為 minmax 的返回值的使用方式比較特殊,通過 .first 和 .second 來分別獲取最小值和最大值,一個示例如下:

 1 // minmax example
 2 #include <iostream>     // std::cout
 3 #include <algorithm>    // std::minmax
 4 int main () {
 5     auto result = std::minmax({1,2,3,4,5});
 6     std::cout << "minmax({1,2,3,4,5}): ";
 7     std::cout << result.first << ' ' << result.second << '\n';
 8     int a = 1, b = 2;
 9     auto result2 = std::minmax(a, b);
10     std::cout << "minmax({1,2}): ";
11     std::cout << result2.first << ' ' << result2.second << '\n';
12     return 0;
13 }
14 /* 輸出結果:
15 minmax({1,2,3,4,5}): 1 5
16 minmax({1,2}): 1 2
17 */

編程要求

本關的編程任務是補全右側代碼片段mainBeginEnd中間的代碼,具體要求如下:

  • main中,首先按照整型、浮點型、字符類型、字符串類型依次讀取數據,然后調用minmax操作(或者minmax操作)計算出最小值和最大值,最后按照示例的格式嚴格輸出最小值和最大值結果。

測試說明

平台將自動編譯補全后的代碼,並生成若干組測試數據,接着根據程序的輸出判斷程序是否正確。

以下是平台的測試樣例:

測試輸入: 53 86

0.04 0.41

g y

ertg erty

預期輸出:

min(53,86)==53

max(53,86)==86

min(0.04,0.41)==0.04

max(0.04,0.41)==0.41

min(g,y)==g

max(g,y)==y

min(ertg,erty)==ertg

max(ertg,erty)==erty

 

輸入格式: 第一行:兩個整型類型數據

第二行:兩個浮點類型數據

第三行:兩個字符類型數據

第四行:兩個字符串類型數據

 

輸出格式: 最后一行末尾有換行符\n!!!

請嚴格參照上述示例預期輸出的格式!!!


開始你的任務吧,祝你成功!

 

 1 //
 2 //  main.cpp
 3 //  step1
 4 //
 5 //  Created by ljpc on 2018/7/2.
 6 //  Copyright © 2018年 ljpc. All rights reserved.
 7 //
 8 
 9 #include <iostream>
10 #include <algorithm>
11 #include <string>
12 #include <cstdio>
13 using namespace std;
14 
15 int main(int argc, const char * argv[]) {
16     
17 
18     // 請在這里補充代碼,完成本關任務
19     /********** Begin *********/
20     int a,b;
21     float c,d;
22     char e,f;
23     string g,h;
24     cin>>a>>b>>c>>d>>e>>f>>g>>h;
25     cout<<"min("<<a<<","<<b<<")=="<<min(a,b)<<endl;
26     cout<<"max("<<a<<","<<b<<")=="<<max(a,b)<<endl;
27     cout<<"min("<<c<<","<<d<<")=="<<min(c,d)<<endl;
28     cout<<"max("<<c<<","<<d<<")=="<<max(c,d)<<endl;
29     cout<<"min("<<e<<","<<f<<")=="<<min(e,f)<<endl;    
30     cout<<"max("<<e<<","<<f<<")=="<<max(e,f)<<endl;    
31     cout<<"min("<<g<<","<<h<<")=="<<min(g,h)<<endl;        
32     cout<<"max("<<g<<","<<h<<")=="<<max(g,h)<<endl;        
33     /********** End **********/
34     
35     return 0;
36 }
點擊查看代碼

 

 

第2關:min函數在自定義數據類型下的應用

任務描述

本關任務:編寫一個程序,基於結構體存儲學生信息,包含學號,姓名和學科成績,並使用模板函數min獲取學科成績較低的學生信息,如果成績相同,則獲取學號靠前的學生信息。

相關知識

為了完成本關任務,你需要掌握:1.自定義數據類型的模板函數min

自定義數據類型的模板函數min

自定義數據類型的的學生信息結構體至少包含三項數據類型:

  1. 整型類型:學號;
  2. 字符串類型:姓名;
  3. 整型類型:學科成績:
1 struct Student{
2     int numberID;
3     char name[20];
4     int score;
5 };

模板函數min在處理自定義數據類型的時候,需要依據該數據類型的比較規則定義一個比較函數,該比較函數返回比較的真值。比如兩個整數 和 

1 bool comp(int a, int b){ return a<b;}
2 int c = min(a, b, comp);

在本關卡中,首先比較學生的成績:若成績不同,則返回成績低的;若成績相同,返回學號靠前的(即數值小的)。模板函數 min 處理自定義數據類型的函數原型如下:

1 template <class T, class Compare>
2 bool comp(const T& a, const T& b);// 按定義的比較規則返回a<b的真值
3 const T& min (const T& a, const T& b, Compare comp);

編程要求

本關的編程任務是補全右側代碼片段 min_cmp 和 main 中 Begin 至 End 中間的代碼,具體要求如下:

  • 在 min_cmp 中,完成兩個學生信息的比較,首先比較學生的成績:若成績不同,則返回成績比較的真值;若成績相同,返回學號比較的真值。
  • 在 main 中,使用結構體讀取和記錄學生信息,並基於模板函數 min 實現學生信息的比較,獲取較小成績的學生信息並輸出。

測試說明

平台將自動編譯補全后的代碼,並生成若干組測試數據,接着根據程序的輸出判斷程序是否正確。

以下是平台的測試樣例:

測試輸入: 

20180108 Henry 54

20180126 Charles 72

預期輸出:

20180108 Henry 54

 

測試輸入:

20180122 Niki 71

20180110 Barbara 71

預期輸出:

20180110 Barbara 71

 

輸入格式:兩行,每行一個學生信息:學號 姓名 成績

輸出格式:一行,輸出學生信息,末尾換行\n


開始你的任務吧,祝你成功!

 

 1 //
 2 //  main.cpp
 3 //  step2
 4 //
 5 //  Created by ljpc on 2018/7/6.
 6 //  Copyright © 2018年 ljpc. All rights reserved.
 7 //
 8 
 9 #include <iostream>
10 #include <algorithm>
11 #include <cstdio>
12 #include <cstring>
13 #include <string>
14 
15 using namespace std;
16 
17 struct Student{
18     int numberID;
19     char name[20];
20     int score;
21     Student(){}
22     Student(int id_, char *name_, int score_){
23         numberID = id_;
24         strcpy(name, name_);
25         score = score_;
26     }
27     void in()
28     {
29         scanf("%d %s %d", &numberID, name, &score);
30     }
31     void out()
32     {
33         printf("%d %s %d\n", numberID, name, score);
34     }
35 };
36 
37 bool min_cmp(Student S1, Student S2){
38     // 請在這里補充代碼,完成本關任務
39     /********** Begin *********/
40     if (S1.score!=S2.score) return S1.score<S2.score;
41     else return S1.numberID<S2.numberID;
42 
43     /********** End **********/
44 }
45 
46 int main(int argc, const char * argv[]) 
47 {    
48     
49     // 請在這里補充代碼,完成本關任務
50     /********** Begin *********/
51     Student stu1,stu2;
52     stu1.in();
53     stu2.in();
54     Student stu;
55     stu=min(stu1,stu2,min_cmp);
56     stu.out();
57  
58     /********** End **********/
59 
60     return 0;
61 }
點擊查看代碼

 

 

第3關:使用模板函數sort對學生成績進行排序

任務描述

本關任務:編寫一個程序,基於結構體存儲N個學生信息,包含學號,姓名和學科成績,並使用模板函數sort完成對學生信息的排序:成績高的排序靠前,若成績相同,則學號小的排序靠前。

相關知識

為了完成本關任務,你需要掌握:1.自定義數據類型下的排序模板函數sort

自定義數據類型下的排序模板函數sort

Algorithm中的排序函數是基於快速排序算法實現的,復雜度為O(N*logN)。快速排序算法在1962年由C. A. R. Hoare提出,其基本思想是:通過一趟排序將待排序的數據分割成獨立的兩部分,左邊部分的所有數據比右邊部分的所有數據都要小,然后再按此方法對這兩部分數據分別進行快速排序,整個排序過程可以遞歸進行,最后達到整個數據變成有序序列。

模板函數sort具有兩種模式,一種是數據之間已有排序規則,比如整型數據、浮點數據,它們的大小比較是確定的;另一種是數據之間沒有現成的排序規則,需要自定義排序規則,這類適用於自定義數據類型。它們函數原型如下:

1 default (1):
2     template <class RandomAccessIterator>
3     void sort (RandomAccessIterator first, RandomAccessIterator last);
4 custom (2):
5     template <class RandomAccessIterator, class Compare>
6     void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);

本關卡是對存儲有N個學生信息的結構體數組進行排序,一般有兩種方式:

  • 在結構體中重載小於比較符<,因為sort函數默認使用<比較符,只要返回this.score>S.score的比較真值,那么使用sort排序將得到成績從高到低的排序結果。由此,最后直接調用sort函數對結構體數組進行排序即可:
 1 struct Student{
 2   int numberID;
 3   char name[20];
 4   int score;
 5   bool operator < (const Student &S)const{ 
 6   //完成結構體比較規則:Student this VS. Student S
 7   //先比較成績,若成績相同,則比較學號
 8   }
 9 }
10 Student student[10];
11 sort(student, student+10);
  • 實現一個結構體比較函數,然后作為參數傳入sort函數完成排序中的結構體間的大小比較:
1 bool max_cmp(Student S1, Student S2){
2 //完成結構體比較規則:Student S1 VS. Student S2
3 //先比較成績,若成績相同,則比較學號
4 }
5 Student student[10];
6 sort(student, student+10, max_cmp);

編程要求

本關的編程任務是補全右側代碼片段 operator max_cmp 和 main 中 Begin 至 End 中間的代碼,具體要求如下:

  • 在 operator < 中,按照先進行學生成績的比較,若成績相等,再比較學號的比較規則,完成結構體 this 和結構體 的大小比較,並返回比較真值。
  • 在 max_cmp 中,按照以上規則完成結構體 S1 和結構體 S2 的大小比較,並返回比較真值。
  • 在 main 中,基於自定義的結構體數據類型讀取和存儲學生信息,然后使用 sort 函數完成學生成績的從大到小排序,最后輸出排序后的學生信息。

測試說明

平台將自動編譯補全后的代碼,並生成若干組測試數據,接着根據程序的輸出判斷程序是否正確。

以下是平台的測試樣例:

測試輸入: 

7

20180127 Helen 88

20180111 Martin 51

20180102 James 88

20180114 Joseph 60

20180106 Joan 99

20180120 Lily 91

20180105 Malcolm 88

預期輸出:

20180106 Joan 99

20180120 Lily 91

20180102 James 88

20180105 Malcolm 88

20180127 Helen 88

20180114 Joseph 60

20180111 Martin 51

 

輸入格式:第一行學生數N,余下 行學生信息

輸出格式: 行排序后的學生信息,每行學生信息中間空格隔開,末尾換行。


開始你的任務吧,祝你成功!

 

 1 //
 2 //  main.cpp
 3 //  step3
 4 //
 5 //  Created by ljpc on 2018/7/6.
 6 //  Copyright ? 2018年 ljpc. All rights reserved.
 7 //
 8 
 9 #include <iostream>
10 #include <algorithm>
11 #include <cstdio>
12 #include <cstring>
13 #include <string>
14 
15 using namespace std;
16 
17 struct Student {
18     int numberID;
19     char name[20];
20     int score;
21     Student() {}
22     Student(int id_, char *name_, int score_) {
23         numberID = id_;
24         strcpy(name, name_);
25         score = score_;
26     }
27     void in() {
28         scanf("%d %s %d", &numberID, name, &score);
29     }
30     void out() {
31         printf("%d %s %d\n", numberID, name, score);
32     }
33     bool operator < (const Student &S)const {//定義sort排序規則,與第2關相同
34         // 請在這里補充代碼,完成本關任務
35         /********** Begin *********/
36         if(score == S.score) return numberID < S.numberID;
37         else return score > S.score;
38         /********** End **********/
39     }
40 };
41 bool max_cmp(Student S1, Student S2) {//定義sort排序規則
42     // 請在這里補充代碼,完成本關任務
43     /********** Begin *********/
44     if(S1.score ==S2.score) return S1.numberID > S1.numberID;//和第2關一樣的算法
45     else return S1.score > S2.score;
46     /********** End **********/
47 }
48 
49 int main(int argc, const char * argv[]) {
50     // 請在這里補充代碼,完成本關任務
51     /********** Begin *********/
52     int a;
53     cin>>a;
54     Student student[a+10];//利用結構體定義一個結構體數組,用於存放學生的數據
55     for(int i=0; i<=a; i++) {//不斷循環獲取學生數據
56         cin>>student[i].numberID>>student[i].name>>student[i].score;
57     }
58     sort(student,student+a);//利用sort函數進行排序
59     for(int i=0; i<a; i++) {//不斷循環輸出每一個學生的數據
60         cout<<student[i].numberID<<" "<<student[i].name<<" "<<student[i].score<<endl;
61     }
62     /********** End **********/
63 
64     return 0;
65 }
點擊查看代碼

 


免責聲明!

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



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