演算法實驗三-遞迴與分治
阿新 • • 發佈:2021-01-09
一、實驗目的:
理解遞迴演算法的思想和遞迴程式的執行過程,並能熟練編寫遞迴程式。
掌握分治演算法的思想,對給定的問題能設計出分治演算法予以解決。
二、實驗環境:
VC6.0
三、實驗內容:
1. Fibonacci數列
無窮數列1,1,2,3,5,8,13,21,34,55,……,稱為Fibonacci數列。它可以遞迴地定義為:
第n個Fibonacci數可遞迴地計算如下:
int fibonacci(int n)
{
if (n <= 1) return 1;
return fibonacci(n-1)+fibonacci(n-2);
}
- 編寫完整的主函式,分別記錄利用上述遞迴函式求第47, 48, 49, 50, 51,52個Fibonacci數所花費的時間。
#include<stdio.h> #include<time.h> int fi(int n) { if(n<=1) return (n); else return(fi(n-1)+fi(n-2)); } int main() { int i; double X; X= clock()/CLOCKS_PER_SEC; for(i=47;i<=52;i++) { X= clock()/CLOCKS_PER_SEC; printf("計算第%d個數 所計算得的結果為%ld\t",i,fi(i)); X= clock() / CLOCKS_PER_SEC-X; printf("計算第%d個的需要的時間為:%f\n",i,X); } }
- 將遞迴函式改為尾遞迴,或者是遞推函式,求第47, 48, 49, 50, 51,52個Fibonacci數所花費的時間,觀察效率是否得到提高。
#include<stdio.h> #include<time.h> double fi(int n) { double F; int Fa,Fb; Fa=0; Fb=1; for(int i=0;i<n;i++){ F=Fa+Fb; Fb=Fa; Fa=F; } return F; } int main() { int i; double X; X= clock()/CLOCKS_PER_SEC; for(i=47;i<=52;i++) { X= clock()/CLOCKS_PER_SEC; printf("計算第%d個數 所計算得的結果為%ld\t",i,fi(i)); X= clock() / CLOCKS_PER_SEC-X; printf("計算第%d個的需要的時間為:%f\n",i,X) } return 0; }
2.角谷定理。
輸入一個自然數n,若n為偶數,則把它除以2,若n為奇數,則把它乘以3加1。用新得到的數重複以上步驟,直到值為1為止。求經過多少次看得到自然數1。
#include <iostream>
using namespace std;
int w = 0;
int jg(int n){
if (n == 1)
{
return 0;
}
else if (n % 2 == 0)
{ n /= 2;
cout<<n<<" ";
if(w==9)
cout<<endl;
w++;
return jg(n);
}
else
{ n = n * 3 + 1;
cout<<n<<" ";
if(w==9)
cout<<endl;
w++;
return jg(n);
}
}
int main() {
int n;
cin >> n;
jg(n);
cout << 經過"<<w <<"次"<< endl;
return 0;
}
實驗結果:
3.走臺階
有n級臺階,可以一步上一個臺階,也可以一步上兩個臺階,編寫程式,計算共有幾種不同的走法。
#include <iostream>
using namespace std;
int w = 0;
int Step(int n){
if (n < 0)
return 0;
if (n == 0){
w++;
return 0;
}
Step(n - 1);
Step(n - 2);
return 0;
}
int main() {
int n;
cin >> n;
Step(n);
cout << "有"<<w <<"種走法"<< endl;
return 0;
}
實驗結果:
4. 半數集問題
問題描述:給定一個自然數n,由n開始可以依次產生半數集set(n)中的數如下:
(1) ;
(2) 在n的左邊加上一個自然數,但該自然數不能超過最近新增的數的一半;
(3) 按此規則進行處理,直到不能再新增自然數為止。
例如,set(6)={6,16,26,126,36,136},半數集set(6)中有6個元素。
輸入:整數n(0<n<1000)
輸出:半數集set(n)中的元素個數。
請設計遞迴函式,求出set(n)的個數,並分析演算法時間複雜度,對演算法進行改進,用程式驗證遞迴演算法,以及改進之後的演算法。
#include<iostream>
#include<time.h>
using namespace std;
int set(int n)
{
int a=1;
if(n>1)
for(int i=1;i<=n/2;i++)
a=a+set(i);
return a;
}
int main()
{
int n;
cout<<"請輸入n值:";
cin>>n;
X= clock()/CLOCKS_PER_SEC;
cout<<"set("<<n<<")的個數為:"<<set(n)<<endl;
X= clock() / CLOCKS_PER_SEC-X;
cout<<"花費的時間為:"<<X<<endl;
return 0;
}
實驗結果:
改進:
#include<iostream>
#include<cstring>
#include<time.h>
using namespace std;
int a[1000];
long set(int n)
{
int an=1;
if(a[n]>0)
return a[n];
for(int i=1;i<=n/2;i++)
an=an+set(i);
a[n]=an;
return an;
}
int main()
{
int n;
double X;
cout<<"ÇëÊäÈënÖµ£º";
cin>>n;
memset(a,0,sizeof(a));
a[1]=1;
X= clock()/CLOCKS_PER_SEC;
cout<<"set("<<n<<")的個數為:"<<set(n)<<endl;
X= clock() / CLOCKS_PER_SEC-X;
cout<<"花費的時間為:"<<X<<endl;
return 0;
}