文章目錄
一、函數定義和調用
二、函數的遞歸調用
從經典的 漢諾塔Hanoi 問題入手
思路如下:
void hanoi(int n, char A, char B, char C)
{
if (n == 1)
move(A, C);
else
{
hanoi(n - 1, A, C, B); //將上面的n-1個藉助C從A移動到B
move(A, C); //將最下面一個從A移到C
hanoi(n - 1, B, A, C); //將n-1個從B藉助A移動到C
}
}
具體代碼:
//將src針的最上面一個盤子移動到dest針上
void move(char src, char dest) {
cout << src << " --> " << dest << endl; }
//將n個盤子從src針移動到dest針,以medium針作爲中轉
void hanoi(int n, char src, char medium, char dest)
{
if (n == 1)
move(src, dest);
else
{
hanoi(n - 1, src, dest, medium);
move(src, dest);
hanoi(n - 1, medium, src, dest);
}
}
int main()
{
int m;
cout << "Enter the number of diskes: ";
cin >> m;
cout << "the steps to moving " << m << " diskes:" << endl;
hanoi(m, 'A', 'B', 'C');
return 0;
}
當函數發生遞歸調用時,同一個局部變量在不同遞歸深度上可以同時存在不同的取值,這在底層是如何做到的?
答:對同一個函數的多次不同調用中,編譯器會爲函數的形參和局部變量分配不同的空間,他們互不影響。
三、函數的參數傳遞
1. 值傳遞
傳遞參數值,單向傳遞
2. 引用傳遞(需要修改形參值的時候使用)
我們常用的交換函數就需要用到引用傳遞,實現雙向傳遞,修改傳進來的形參值
void swap(int &a, int &b){
int temp = a;
a = b;
b = temp;
學習 引用傳遞 需詳細掌握以下 引用 的知識
變量的引用
int &r = n;
某個變量的引用,等價於這個變量(即同一個人,不管誰發生改變,另一個也會隨之改變)
int n = 7;
int &r = n; //定義引用時一定要將其初始化引用某個*變量*
r = 4;
cout<<r; //4
cout<<n; //4
n = 5;
cout<<r; //5
int a = 4;
int b = 5;
int &r1 = a;
int &r2 = r1; //等價於 int &r2 = a; r2也引用a
r2 = 10;
cout<<a; //10
一旦一個引用被初始化後,就不能改爲指向其他對象
int a = 4;
int b = 5;
int &r1 = a;
//*一個引用是從一而終的*,該語句並不表示r1引用了b,而是b的值賦給了r1
r1 = b;
cout<<a; //5
引用作爲函數的返回值
int n = 4;
int &setValue(){ //返回了n的引用
return n;
}
int main(){
setValue() = 40; //函數返回的是n的引用,所以可以作爲左值被賦值
cout<<n; //給n的引用賦值40 等價於 給n賦值40
}
常引用
const int &r = n;
不能通過常引用去修改其引用的內容
int n = 100;
const int &r = n;
r = 50; //wrong
n = 49; //right n的引用r的值也隨之改變
三、內聯函數
內聯函數的調用過程:
inline int Max(int a, int b){
if(a>b)
return a;
return b;
}
假如主函數中有如下語句
K = Max(n1,n2);
等價於
if(n1 > n2)
tmp = n1;
else
tmp = n2;
K = tmp;
即直接把函數體嵌入到代碼中,而沒有函數調用的出入棧的過程。
編譯器並不承諾將inline修飾的函數作爲內聯,而在現代編譯器中,沒有inline修飾的函數也可能被編譯爲內聯
四、帶默認形參值的函數(缺省函數)
在相同的作用域內,不允許在同一個函數的多個聲明中對同一個參數的默認值重複定義,即使前後定義的值相同也不行。
五、函數重載(形參個數/類型不同)
函數重載提高了程序的可擴充性。
(C語言中不允許同名函數,即沒有重載的概念)
注:編譯器不以形參名和返回值來區分重載。 若只有返回值類型不同,則不叫重載,叫重複定義
double func(int a, string var){ };
int func(int x, string b){ };
六、典型例題
1. 數制轉換
double power(double x, int n); //x的n次方
int main(){
int value = 0;
cout<<"please enter 8 bit binary number:";
for(int i = 7; i>=0; i--){ //從高位往低位讀入二進制數
char ch;
cin>>ch; //以字符形式讀取
if(ch == '1')
//強轉
value += static_cast<int>(power(2,i)); //value += (int)(power(2,i));
}
cout<<"decimal value is "<<value<<endl;
return 0;
}
double power(double x, int n){
double sum = 1.0;
while(n--)
sum = sum*x;
return sum;
}
或者用數學方式處理
//以int形式讀入的數學方式處理
while ( binary != 0 )
{
decimal += binary % 10 * bit;
binary /= 10;
bit *= 2;
}
2. 編寫程序求 π 的值
double arctanx(double x)
{
double sqr = x * x; //x每次都乘以x2
double e = x; //保存x的次方,分子
double sum = 0; //保存最終結果
int i = 1; //分母
int flag = 1;
while (e / i > 1e-15)
{
double f = flag * e / i;
sum += f;
e = e * sqr;
i += 2;
flag = -flag;
}
return sum;
}
int main()
{
//注意:因爲整數相除結果取整,如果參數寫1/5,1/239,結果就都是0
double a = 16.0 * arctanx(1 / 5.0);
double b = 4.0 * arctanx(1 / 239.0);
cout << "PI = " << a - b << endl;
return 0;
}
3. 擲骰子
- 每個骰子有六面,點數分別爲1、2、3、4、5、6。遊戲者在程序開始時輸入一個無 符號整數,作爲產生隨機數的種子。
- 每輪投兩次骰子,第一輪如果和數爲7或11則爲勝,遊戲結束;和數爲2、3或12 則爲負,遊戲結束;和數爲其它值則將此值作爲自己的點數,繼續第二輪、第三輪…直到 某輪的和數等於點數則取勝,若在此前出現和數爲7則爲負。
此處需要用到 rand
函數,rand產生的是僞隨機數,即每次運行產生的是同一串隨機數序列
//投骰子、計算和數、輸出和數
int rollDice()
{
int die1 = 1 + rand() % 6;
int die2 = 1 + rand() % 6;
int sum = die1 + die2;
cout << "player rolled " << die1 << " + " << die2 << " = " << sum << endl;
return sum;
}
enum GameStatus
{
WIN,
LOSE,
PLAYING
};
int main()
{
int sum, myPoint;
GameStatus status;
unsigned seed;
cout << "Please enter an unsigned integer: ";
cin >> seed; //輸入隨機數種子
srand(seed); //將種子傳遞給rand()
sum = rollDice(); //第一輪投骰子、計算和數
switch (sum)
{
case 7: //如果和數爲7或11則爲勝,狀態爲WIN
case 11:
status = WIN;
break;
case 2: //和數爲2、3或12則爲負,狀態爲LOSE
case 3:
case 12:
status = LOSE;
break;
default: //其它情況,尚無結果,狀態爲 PLAYING,記下點數
status = PLAYING;
myPoint = sum;
cout << "point is " << myPoint << endl;
break;
}
while (status == PLAYING)
{ //只要狀態爲PLAYING,繼續
sum = rollDice();
if (sum == myPoint) //某輪的和數等於點數則取勝
status = WIN;
else if (sum == 7) //出現和數爲7則爲負
status = LOSE;
}
//當狀態不爲PLAYING時循環結束,輸出遊戲結果
if (status == WIN)
cout << "player wins" << endl;
else
cout << "player loses" << endl;
return 0;
}
4. 遞歸計算從n個人中選k個人不同組合數。
int comm(int n, int k)
{
if (k > n)
return 0;
else if (n == k || k == 0)
return 1;
else
return comm(n - 1, k) + comm(n - 1, k - 1);
}
5. 遞歸實現 getPower 計算 x的y次方
此處需要考慮兩種情況,x是整數 和 x是小數 ,利用重載編寫兩個做同樣運算的函數 getPower
👉 👉 👉 原文首發 - 小牛肉的個人博客,歡迎來訪~👈 👈 👈