1. 程式人生 > >遞迴演算法及經典案例

遞迴演算法及經典案例

遞迴是程式設計中的一種演算法。一個過程或函式直接呼叫自身或通過其他的過程或函式呼叫語句間接地呼叫自己的過程或函式,稱為遞迴過程或函式。

遞迴是較難理解的演算法之一。簡單地說,遞迴就是編寫這樣一個特定的過程,該過程中有一個語句用於呼叫過程自身。

好了,不多說了,看幾個案例吧!

案例1:利用遞迴呼叫手段程式設計計算N!。

template <typename T>
T find(T n)  //遞迴函式
{
	if (n == 1)
	{
		return 1;
	}
	else
	{
		return find(n - 1)*n;
	}
}
int _tmain(int argc, _TCHAR* argv[])
{
	int n;
	cout << "Please input n:" << endl;
	cin >> n;
	cout << "n! = " << find(n) << endl;

	return 0;
}
案例2:試用遞迴的方法寫一個計算斐波那契數列的通項f(n),已知f1=1,f2=1,以後每項都是前兩項的和。
template <typename T>
T f(T n)  //遞迴函式
{
	if (n == 1 || n == 2)
	{
		return 1;
	}
	else
	{
		return f(n - 1) + f(n - 2);
	}
}
int _tmain(int argc, _TCHAR* argv[])
{
	int n;
	cout << "Please input n:" << endl;
	cin >> n;
	cout << "n! = " << f(n) << endl;

	return 0;
}

案例3:一個射擊運動員打靶,靶一共有10環,連開10槍打中90環的可能性有多少種?

如果用非遞迴的方法實現,可以用10個迴圈語句來表示程式,程式碼如下:

for(i1=0;i1<10;i1++)
{
    for(i2=0;i2<10;i2++)
    {
        ...
        if(i1+...+i9==90)
        Print();
        ...
    }
}
上面的程式碼可以解決問題,但是時間複雜度和空間複雜度無疑是很高的。
#include "stdafx.h"
#include <iostream>
using namespace std;

int sum = 0;
int socre[10];

//輸出每次射擊打中的環數
void Output()
{
	for (int i = 0; i < 10;i++)
    {
		cout << socre[i] << "\t";
    }
	cout << endl;
	sum++;
}
//統計滿足條件的次數
template <typename T>
void Compute(T Sum_Socre, T n)
{
	if (Sum_Socre < 0 || Sum_Socre > (n + 1) * 10)//次數n為0-9
		return;
	if (n == 0)
	{
		socre[n] = Sum_Socre;
		Output();
		return;
	}
	for (T i = 0; i <= 10;i++)
	{
		socre[n] = i;
		Compute(Sum_Socre - i, n - 1);
	}
}
int _tmain(int argc, _TCHAR* argv[])
{
	Compute(90, 9);
	cout << sum << endl;
	return 0;
}
案例4:八皇后問題。該問題是19世紀著名的數學家高斯1850年提出:在8×8格的國際象棋盤上擺放8個皇后,使不能互相攻擊,即任意兩個皇后都不能 處於同一行、同一列或同一斜線上,問有多少種擺法。

演算法解析:

陣列a、b、c分別用來標記衝突,a陣列代表列衝突,從a[0]-a[7]代表第0列到第7列。如果某列上已有皇后,則為1,否則為0.

陣列b代表主對角線衝突,為b[i-j+7],即從b[0]-b[14]。如果某條主對角線上已經有皇后,則為1,否則為0.

陣列c代表從對角線衝突,為b[i+j],即從c[0]-b[14]。如果某條從對角線上已經有皇后,則為1,否則為0.