算法实验三-递归与分治

本文探讨了递归算法在计算Fibonacci数列中的应用,比较了递归、尾递归和递推方法的效率。接着,通过角谷定理实例演示了分治策略,并针对走台阶和半数集问题进行了递归与优化算法的实现。最后,分析了半数集问题的改进算法及其时间复杂度。

一、实验目的:

  理解递归算法的思想和递归程序的执行过程,并能熟练编写递归程序。

掌握分治算法的思想,对给定的问题能设计出分治算法予以解决。

二、实验环境:

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);

   }

  1. 编写完整的主函数,分别记录利用上述递归函数求第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);

 }

}
  1. 将递归函数改为尾递归,或者是递推函数,求第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;
}

实验结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值