函數的進階應用 10 戰勢不過奇正,奇正之變,不可勝窮也。 奇正相生,如循環之無端,孰能窮之哉! 《孫子兵法﹒勢篇》

Slides:



Advertisements
Similar presentations
1 第二讲 C++ 编程基础. 2 主要内容 C++ 语言概述 C++ 编程基础 数据的简单输入输出 C++ 的发展 C++ 源程序结构与书写规范 C++ 编译器和集成开发环境.
Advertisements

第一單元 建立java 程式.
計算機程式語言實習課.
第4章 数组 数组是由一定数目的同类元素顺序排列而成的结构类型数据 一个数组在内存占有一片连续的存储区域 数组名是存储空间的首地址
第8章 字串與陣列 8-1 字串處理 8-2 一維陣列的處理 8-3 建立多維陣列 8-4 不規則陣列與參數傳遞 8-5 陣列排序與搜尋.
Chapter 5 遞迴 資料結構導論 - C語言實作.
struct 可以在同一個名稱下擁有多種資料型態。使用struct能讓資料的存取和處理更為靈活。
簡易C++除錯技巧 長庚大學機械系
資料大樓 --談指標與陣列 綠園.
函數(一) 自訂函數、遞迴函數 綠園.
快速排序法 (Quick Sort).
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
刘胥影 东南大学计算机学院 面向对象程序设计1 2011~2012第3学期 刘胥影 东南大学计算机学院.
C++语言程序设计 C++语言程序设计 第四章 数组及自定义数据类型 C++语言程序设计.
第一章 程序的基本结构. 第一章 程序的基本结构 教材及授课结构 本章目标 基本内容 扩展阅读 上机指导 应用举例 习题.
C++语言程序设计 C++语言程序设计 第四章 数组及自定义数据类型 C++语言程序设计.
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
Object-Oriented Programming in C++ 第一章 C++的初步知识
前處理指令可以要求前處理器 (preprocessor) 在程式編譯之前,先進行加入其它檔案的內容、文字取代以及選擇性編譯等工作。
2 C++ 的基本語法和使用環境 親自撰寫和執行程式是學好程式語言的不二法門。本章藉由兩個簡單的程式,介紹C++ 程式的基本結構和開發環境,讓初學者能逐漸建立使用C++ 的信心。
程式撰寫流程.
類別(class) 類別class與物件object.
SQL Stored Procedure SQL 預存程序.
第3讲 C++程序控制结构 3.1 顺序结构 3.2 分支结构 3.3 循环结构 3.4 转向控制 3.5 综合案例分析.
C++程序设计 string(字符串类) vector(容器类).
Chapter 3 – Functions 函式 目標 能夠明白如何利用一些函式、用模組化的方式建立程式 能夠建立新的函式
C++语言程序设计 第二章 C++简单程序设计.
程序的三种基本结构 if条件分支语句 switch多路开关语句 循环语句 循环嵌套 break,continue和goto语句
3 數學運算 3.1 鍵盤輸入 輸入函數cin 多重輸入cin 輸出格式化 3-3
谭浩强 编著 中国高等院校计算机基础教育课程体系规划教材 C++程序设计.
C++语言程序设计 第十一章 流类库与输入/输出.
切換Dev c++顯示語言 工具->環境選項(V)->介面->language (Chinese TW)
第一單元 建立java 程式.
選擇性結構 if-else… switch-case 重複性結構 while… do-while… for…
六、函数 教学目标: 函数的概念、定义、调用和返回 带自定义函数的程序设计 递推算法 递归思想及算法实现 函数的参数传递方式 C语言程序设计.
C++大学基础教程 第3章 C++控制语句 北京科技大学 信息基础科学系.
開始使用Visual C++.
Name1..hour //加班時數 name2..hour //請假時數
第二章 基本数据类型及运算 C数据类型概述 基本数据类型 运算符和表达式 混合运算与类型转换 数据的输入输出 顺序程序设计举例.
C++语言程序设计 C++语言程序设计 第五章 函数 第十一组 C++语言程序设计.
資料結構與C++程式設計進階 排序與搜尋 講師:林業峻 CSIE, NTU 6/ 14, 2010.
C++语言程序设计 C++语言程序设计 第三章 控制语句 第十一组 C++语言程序设计.
Oop8 function函式.
物件導向程式設計 CH2.
第11章 從C到C++語言 11-1 C++語言的基礎 11-2 C++語言的資料型態與運算子 11-3 C++語言的輸出與輸入
函數 博碩文化出版發行.
C qsort.
C++程式設計入門 變數與運算子 作者:黃建庭.
C/C++基礎程式設計班 C++: 物件的使用、參考、重載函式 講師:林業峻 CSIE, NTU 3/28, 2015.
亂數 隨機產生亂數 Random類別支援的方法: Next多載方法 Next :傳回亂數。
陣列與結構.
隨機數 (亂數) 10後,取餘數 n = rand(); 利用 Code::Block 驗證一下 n = rand() %10; 998
第 3 章 类的基础部分 陈哲 副教授 南京航空航天大学 计算机科学与技术学院.
挑戰C++程式語言 ──第9章 函數.
#include <iostream.h>
C++语言程序设计 C++语言程序设计 第八章 继承 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第二章 基本数据类型与表达式 第十一组 C++语言程序设计.
選擇性結構 if-else… switch-case 重複性結構 while… do-while… for…
C++语言程序设计 C++语言程序设计 第十章 多态 第十一组 C++语言程序设计.
《数据结构与算法设计》第一部分 面向对象的C++程序设计基础.
Chap 6 函數 故用兵之法,十則圍之,五則攻之,倍則分之, 敵則能戰之,少則能逃之,不若則能避之。 故小敵之堅,大敵之擒也。
第四章 陣列、指標與參考 4-1 物件陣列 4-2 使用物件指標 4-3 this指標 4-4 new 與 delete
C++语言程序设计 C++语言程序设计 第十一章 异常处理 C++语言程序设计.
變數與資料型態  綠園.
Array(陣列) Anny
資料!你家住哪裏? --談指標 綠園.
微 處 理 機 專 題 – 8051 C語言程式設計 主題:階乘計算
隨機函數.
方法(Method) 函數.
C++语言程序设计 C++语言程序设计 第二章 基本数据类型与表达式 第十一组 C++语言程序设计.
Presentation transcript:

函數的進階應用 10 戰勢不過奇正,奇正之變,不可勝窮也。 奇正相生,如循環之無端,孰能窮之哉! 《孫子兵法﹒勢篇》 戰勢不過奇正,奇正之變,不可勝窮也。 奇正相生,如循環之無端,孰能窮之哉! 《孫子兵法﹒勢篇》 介紹函數的重載、參數的預設值、樣版函數,等等讓 C++ 的函數在使用上更方便的語法。此外,也討論了幾個非常實用的問題,包括如何取得亂數、遞迴函數的設計以及排序與搜尋的相關演算法。

Chap 10 函數的進階應用 10.1 函數的重載 10.2 參數的預設值 10.3 樣版函數 10.4 亂數的取得 10.5 遞迴函數 10.1 函數的重載 10.2 參數的預設值 10.3 樣版函數 10.4 亂數的取得 10.5 遞迴函數 10.6 排序與搜尋

函數的重載 int Max(int, int); double Max(double, double); // 參數的資料型態不同 double Area(double x); double Area(double x, double y); // 參數的數目不一樣

範例程式 Overload.cpp: 函數的重載 #include <iostream> using namespace std; // 函數的原型 double Max(double, double); double Max(double, double, double);// 參數的數目不一樣

//------- 主程式 --------------------------------- int main() { double a=5.0, b=6.0, c=7.0; cout << "Max(a, b) 的值是: " << Max(a, b) << endl; cout << "Max(a, b, c) 的值是: " << Max(a, b, c) << endl; return 0; }

// --- 函數的定義 -------------------------- double Max(double x, double y) { return (x>=y) ? x : y;} double Max(double x, double y, double z) { double Temp = x; if (x<y) Temp = y; if (Temp<z) Temp = z; return Temp; } 程式執行結果 Max(a, b) 的值是: 6 Max(a, b, c) 的值是: 7

預設引數 (default arguments) 函數原型: double Area(double Width, double Length = 12.0); 函數定義(兩個參數的乘積): double Area(double Width, double Length) { return Width*Length; } A = Area(6.5); // 只用一個引數呼叫

範例程式 Default.cpp: 預設引數 // Default.cpp #include <iostream> using namespace std; // --- 宣告函數Area() -------------------- double Area(double Width, double Length = 12.0); // --- 主程式 ---------------------------- int main() { double A; A = Area(6.5); // 只用一個參數呼叫 return 0; } // --- 定義函數Area() -------------------- double Area(double Width, double Length) { return Width*Length; }

預設引數函數的呼叫 void Fune (float, float x = 0,int n = 5,char = "r"); 下面的呼叫都是正確的: Func(1.5); Func(3.2, 1.0); Func(0.0, 1.0, 10, 'a'); 不可以有下列的呼叫方式: Func(1.0, 2.0, 'a'); // 錯誤!

具有預設參數的重載函數 兩個具有預設參數的重載函數Func()之原型: int Func(int n, int m = 0, float x = 1.0); int Func(int n, int m); 這兩個函數無法以下列呼叫敘述正確區分: M = Func(2,3);    // 錯誤!

樣版函數(Function Template) template <class T> T Sum(T x, T y) {return x+y;} 相當於同時宣告了許多名稱都叫做Sum() 的函數,但其輸入和輸出的資料型態未定。 樣版函數內可以使用不只一種暫定的資料型態: template <class T1, class T2, class T3> T1 Func(T1 x,T2 y, T3 z) {    // … 函數內容 }

樣版函數可以用來取代函數的重載 template<class T> T Abs(T x) {return (x>0)? x : -x;} 相當於同時定義了三個函數: int Abs (int x) {return (x>0)? x : -x;} float Abs (float x) {return (x>0)? x : -x;} double Abs (double x) {return (x>0)? x : -x;}

準亂數產生器(pseudo-random number generator) rand() :可以產生0到RAND_MAX的整數。 RAND_MAX定義在 <cstdlib> 裏面,RAND_MAX的值通常為 0x7FFFU (32767)。 srand() 用來給予這個準亂數產生器一個臨時的初始值 (稱為種子,seed)。 srand(int(time(0)));

產生指定範圍內的整數亂數 獲得一個介於0到N-1之間的整數亂數: rand()%N 我們可以包裝成inline 函數以方便使用: inline int RandI(int N) {return 1 + rand()%N;}

範例程式 TestDice.cpp // TestDice.cpp #include <iostream> 以inline 函數 RandI() 為基礎,寫成一個函數TestDice() 以模擬擲骰子的 現象 (骰子的值為整數1~6)。 // TestDice.cpp #include <iostream> #include <iomanip> #include <ctime> using namespace std; inline int RandI(int N) // 定義 inline 函數 RandI() { return rand()%N+1; } void TestDice(); // 宣告函數 TestDice() const int TestNum = 6000;

//------- 主程式 ---------------------- int main() { cout << right << fixed << showpoint << setprecision(4); cout << "RAND_MAX (0x7FFFU) 的值是 :" << setw(7) << RAND_MAX << endl; TestDice(); return 0; }

//------- 定義函數 TestDice() --------- void TestDice() { int Freq[6], Face, i; for (i=0; i<6; i++) Freq[i]=0; // (1) 初始化 srand(int(time(0))); // (2) 連擲 20 次 cout << "連擲 20 次的結果: " << endl; for (i=1; i<=20; i++) cout << setw(5) << RandI(6); if (i%5 == 0) cout << endl; } cout << endl;

// (3) 統計連擲 TestNum 次的結果 for (int Roll=0; Roll< TestNum; Roll++) { Face = RandI(6); Freq[Face-1]++; } cout << " 點數 次數 " << endl; cout << "------------------ " << endl; for (i=0; i<6; i++) cout << setw(5) << (i+1) << setw(10) << Freq[i] << endl; cout << "------------------ " << endl;

程式執行結果 RAND_MAX (0x7FFFU) 的值是:32767 LRAND_MAX (0x7FFFFFFFU) 的值是:2147483647 連擲20次的結果: 1 1 4 3 4 2 6 2 5 1 4 6 1 4 5 2 2 3 1 4 點數 次數 ------------------ 1 1002 2 1027 3 1005 4 980 5 972 6 1014

隨機獲得一個介於0到1之間的浮點數 inline double Rand() {return double(rand())/RAND_MAX;}

範例程式 檔案 TestRand.cpp 藉由程式模擬連續隨機產生20個浮點數的過程。接著,統計連連續產生6000次的結果,以查看各個範圍內出現的次數是否均勻(每個範圍間隔0.1)。最後,將6000次的結果平均 (理想值為中間值0.5),以驗證準亂數產生器的性能。

#include <iostream> #include <iomanip> #include <stdlib> using namespace std; // 定義 inline 函數 Rand() 產生 0 ~ 1 之間的亂數 inline double Rand() {return double(rand())/RAND_MAX;} //------- 宣告函數 TestRand() --------- void TestRand(); const int TestNum = 6000; //------- 主程式 ---------------------- int main() { cout << right << fixed << showpoint << setprecision(4); TestRand(); return 0; }

//------- 定義函數 TestRand() --------- void TestRand() { int Freq[10]; double Sum, Temp; // (1) 初始化 srand(int(time(0))); // 也可寫成 randomize(); for (int i=0; i<10; i++) Freq[i]=0; // (2) 連試 20 次 Rand() cout << "連試 20 次 Rand(): " << endl; for (int i=1; i<=20; i++) cout << setw(10) << Rand(); if (i%5 == 0) cout << endl; } cout << endl; // (3) 統計連試 TestNum 次的結果 Sum = 0.0;

for (int Roll=0; Roll< TestNum; Roll++) { Temp = Rand(); for (int i=1; i<=10; i++) if ((Temp<=i*0.1) && (Temp>(i-1)*0.1)) Freq[i-1]++; Sum += Temp; } cout << " 範圍 次數 " << endl; cout << "--------------------------------- " << endl; cout << ((i-1)*0.1) << " < Rand() <= " << (i*0.1) << setw(6) << Freq[i-1] << endl; cout << "平均: " << Sum/double(TestNum) << endl; return;

程式執行結果 連試20次Rand(): 0.1886 0.3008 0.6612 0.6320 0.0216 0.1375 0.7226 0.3215 0.0080 0.6875 0.7928 0.5995 0.7400 0.4369 0.8018 0.9930 0.6493 0.0373 0.8551 0.6647 範圍 次數 --------------------------------- 0.0000 < Rand() <= 0.1000 605 0.1000 < Rand() <= 0.2000 601 0.2000 < Rand() <= 0.3000 560 0.3000 < Rand() <= 0.4000 600 0.4000 < Rand() <= 0.5000 602 0.5000 < Rand() <= 0.6000 648 0.6000 < Rand() <= 0.7000 550 0.7000 < Rand() <= 0.8000 643 0.8000 < Rand() <= 0.9000 608 0.9000 < Rand() <= 1.0000 583 平均: 0.5014

遞迴函數: 階乘(factorial) n的階乘,寫成 n !,的定義式為

範例程式 Factorial.cpp: 遞迴函數Factorial() #include <iostream> using namespace std; // --- 宣告遞迴函數 Factorial() -------------------- int Factorial(int); // ---- 主程式 ------------------------------------- int main() { int N; cout << "請輸入一個 12 以下的正整數: "; cin >> N; if ( N < 0 ) cout << "錯誤! 您輸入了負數." << endl; else cout << N << " ! = " << Factorial( N ) << endl; return 0; }

// --- 定義遞迴函數 Factorial() ---------------------- int Factorial(int N) { if ( N <= 1 ) return 1; else return N * Factorial(N-1); // 呼叫自己! } 程式執行結果 請輸入一個 12 以下的正整數: 10 10 ! = 3628800

最大公約數 (Greatest Common Divider,簡寫為GCD) 正整數M和N的最大公約數,寫成GCD(M,N),的定義式為 可以使用C++寫成遞迴函數GCD(),列於檔案GCD.cpp中。

範例程式 GCD.cpp // GCD.cpp #include <iostream> using namespace std; int GCD(int, int); // ---- 主程式 ---------------------------------- int main() { int Num1, Num2; cout << "請輸入第一個正整數 (共兩個): " << endl; cin >> Num1; cout << "請輸入第二個正整數 (共兩個): " << endl;; cin >> Num2; cout << Num1 << " 和 " << Num2 << " 的最大公約數是 " << GCD(Num1, Num2); return 0; }

// --- 定義函數 GCD() -------------------------- int GCD(int M, int N ) { if ( (M%N) == 0 ) return N; else return GCD(N, M%N); }

泡沫排序法 假設資料的名稱叫做Data,而且資料的數量是Size,則泡沫排序法 的虛擬程式碼 (pseudocode): for (int i = 0; i < Size; i++) for (int j = Size; j > i; j--) if (Data[j] < Data[j-1]) 交換 V[j] 和V[j-1] 的值

範例程式 Bubble.cpp // Bubble.cpp #include <iostream> #include <iomanip> using namespace std; // --- 定義樣版函數 Exchange() ---------------------- template <class T> void Exchange(T& A, T& B) { T Temp; Temp = A; A=B; B=Temp; } template <class T> // --- 定義樣版函數 Bubble() void Bubble(T *V, int N ) for (int i=0; i<N; i++) for (int j=N-1; j>i; j--) if (V[j]<V[j-1]) Exchange(V[j],V[j-1]); return;

inline double Rand() // 定義 inline 函數 Rand() {return double(rand())/RAND_MAX;} // ---- 主程式 ------------------------------------- int main() { srand(int(time(0)));; const int Size = 20; double Data[Size]; for (int i=0; i<20; i++) Data[i]= 10.0*Rand()-5.0; // 隨機產生 Data[i] cout << setiosflags(ios::right) << setiosflags(ios::fixed) << setiosflags(ios::showpoint)<< setprecision(4); cout << "\n執行 Bubble() 之前, Data 的值是:\n"; for (int i=0; i<Size; i++) cout << setw(10) << Data[i]; if (i%5 == 4) cout << endl; }

Bubble(Data, Size); cout << "\n執行 Bubble() 之後, Data 的值是:\n" for (int i=0; i<Size; i++) { cout << setw(10) << Data[i]; if (i%5 == 4) cout << endl; } return 0;

程式執行結果 執行Bubble() 之前, Data的值是: 1.9149 -2.1917 -3.7524 0.3801 -2.1551 1.9149 -2.1917 -3.7524 0.3801 -2.1551 -2.6949 4.9835 -2.7267 -0.1643 4.3005 0.2831 1.3082 2.4410 -4.0802 4.0301 1.3158 0.8391 -2.1691 -1.3640 -3.8464 執行Bubble() 之後, Data的值是: -4.0802 -3.8464 -3.7524 -2.7267 -2.6949 -2.1917 -2.1691 -2.1551 -1.3640 -0.1643 0.0000 0.2831 0.3801 0.8391 1.3082 1.3158 1.9149 2.4410 4.0301 4.3005

線性搜尋法 假設資料的名稱叫做 Data,而且資料的數量是 Size,比對的標準為 key,則線性搜尋法的虛擬程式碼為: for (int i = 0; i < Size; i++) if (Data[i] == Key) 傳回 i; 傳回 -1;

範例程式 檔案 LinearSearch.cpp #include <iostream> #include <iomanip> #include <stdlib> using namespace std; // --- 定義樣版函數 LinSearch() ----------------------- template <class T> int LinSearch(T *V, int N , T Key) { for (int i=0; i<N; i++) { if (V[i] == Key) return i; } return -1; }

// -- 定義 inline 函數 RandI() 產生 1~N 之間的亂數 ------ inline int RandI(int N) {return rand()%N+1;}

// ---- 主程式 -------------------------------------- int main() { int Index; int Key = 32; srand(int(time(0))); const int Size = 20; int Data[Size]; for (int i=0; i<20; i++) Data[i]= RandI(85); // 隨機產生 Data[i] cout << "\nData 的值是:" << endl;

for (int i=0; i<Size; i++) { cout << setw(10) << Data[i]; if (i%5 == 4) cout << endl; } Index = LinSearch(Data, Size, Key); if (Index > -1) cout << Key << " 在第 " << Index+1 << " 個元素的地方." << endl; else cout << "找不到 " << Key << endl; return 0;

程式執行結果 (第一次執行結果) Data的值是: 74 72 82 16 29 35 7 9 20 43 46 10 27 65 7 74 72 82 16 29 35 7 9 20 43 46 10 27 65 7 47 49 18 58 50 找不到 32 (第二次執行結果) 52 31 27 30 73 83 5 33 33 67 58 17 61 39 84 67 80 32 79 52 32在第18個元素的地方

二分搜尋法 (binary search) 如果資料本身已經按照大小排序,就可以用二分搜尋法 以提高搜尋的效率。 假設資料的名稱叫做Data,而且資料的數量是Size,比對的標準為key,中間元素的下標叫做Mid,元素值較小的那一邊的下標範圍從Left到Mid-1,元素值較丈的那一邊的下標範圍從Mid+1到Right,則二分搜尋法的虛擬程式碼為: int Left =0, Right, Mid; Right = N-1;

當 (Left <= Right) 時執行下列敘述 { Mid = (int) ((Left+Right)/2); if (Key == Data[Mid]) 傳回 Mid; else if (Key > Data[Mid]) Left = Mid +1; else Right = Mid -1; } 傳回 -1;

範例程式 檔案 BinarySearch.cpp // --- 定義樣版函數 Bubble() ----------------------- template <class T> void Bubble(T *V, int N ) { for (int i=0; i<N; i++) for (int j=N; j>i; j--) if (V[j]<V[j-1]) Exchange(V[j],V[j-1]); return; }

// ---- 主程式 ------------------------------------- int main() { int Index, Key = 32; srand(int(time(0))); const int Size = 20; int Data[Size]; for (int i=0; i<20; i++) Data[i]= RandI(85); // 隨機產生 Data[i] cout << "\nData 原來的值是:\n"; for (int i=0; i<Size; i++) { cout << setw(10) << Data[i]; if (i%5 == 4) cout << endl; }

Bubble(Data, Size); cout << "\n執行 Bubble() 之後, Data 的值是:\n"; for (int i=0; i<Size; i++) { cout << setw(10) << Data[i]; if (i%5 == 4) cout << endl; } Index = BiSearch(Data, Size, Key); if (Index > -1) cout << Key << " 在第 " << Index+1 << " 個元素的地方.\n"; else cout << "找不到 " << Key << endl; return 0;