C/C++算法设计实验报告(源代码)

算法分析

请查看:
算法分析文章

程序源代码:

#include <iostream>
#include <time.h>
#include <stdlib.h>
#include <conio.h>
#define N 200
#define MaxVertices 100 //假设包含100个顶点
#define MaxWeight 32767 //不邻接时为32767,但输出时用 "∞"
#define MAXV 10
#define INF 32767
using namespace std;
typedef struct{ //包含权的邻接矩阵的的定义
    int Vertices[MaxVertices];  //顶点信息的数组
    int Edge[MaxVertices][MaxVertices]; //边的权信息的数组
    int numV; //当前的顶点数
    int numE; //当前的边数
}AdjMatrix;


typedef struct array
{
	int *a;
	int n;
}Array;

void menu()//主菜单 
{	
//标题头 
	cout<<"				-----------------------------------------------------				"<<endl;
	cout<<"             					《算法设计与分析》实验"<<endl;
	cout<<"				-----------------------------------------------------"<<endl;
//选择菜单
	cout<<"				  1.算法分析基础——Fibonacci序列问题" <<endl;
	cout<<"				  2.分治法在数值问题中的应用——矩阵相乘问题 "<<endl;
	cout<<"				  3.减治法在数值问题中的应用——8枚硬币问题 "<<endl;
	cout<<"				  4.变治法在数值问题中的应用——堆排序问题 "<<endl;
	cout<<"				  5.动态规划法在图问题中的应用——全源最短路径问题 "<<endl;
	cout<<"				  99.退出本实验" <<endl;
	cout<<"				-----------------------------------------------------"<<endl;
	cout<<"				  请输入您所要执行的操作(1,2,3,4,5,99);"<<endl;
	
}

//Fibonacci算法实现阶段 
//Fibonacci数列
int Fi(int i)
{
	if(i<=1)
		return i;
	else
		return Fi(i-1)+Fi(i-2);
}

void Fn()
{
	int i=0,j=0;
	do
	{
		j=Fi(i);
		if(j>=0)
			printf("%d  ",j);
		++i;
	}while(j>=0);
	printf("\n计算机所能计算的最大整数是第%d个fibonacci整数。\n",i-1);
}

void Fib()
{ 
	int i=1,f[3]={0,1};
	printf("%d  \n",f[0]);
	do
	{	
		printf("%d  \n",f[1]);
		f[2]=f[1]+f[0];
		f[0]=f[1];
		f[1]=f[2];
		i++;
	}while(f[1]>=f[0]);
	printf("\n\t计算机所能表示的最大fibonacci整数是第%d个fibonacci整数。\n",i);
}

void fibonacci()
{
	double start;
	start=clock();
	Fib();
	printf("\t迭代所用时间是%lf \n\n",clock()-start);
	start=clock();
	Fn();
	printf("\t递归所用时间是%lf \n\n",clock()-start);
}



//矩阵相乘问题求解 
void PrintIn(Array A,Array B)
{
	int n=A.n;
	int i,j;
	printf("请输入A数据:\n");
	for(i=0;i<n;i++)
         for(j=0;j<n;j++)
			 cin>>A.a[i*n+j];
    printf("请输入B数据:\n");
	for(i=0;i<n;i++)
         for(j=0;j<n;j++)
           cin>>B.a[i*n+j];
}

void RandomIn(Array A,Array B)
{
	int n=A.n;
	srand((unsigned)time(NULL));
	int i,j;
	for(i=0;i<n;i++)
		for(j=0;j<n;j++)
			A.a[i*n+j]=rand()%10;
		
	for(i=0;i<n;i++)
	   for(j=0;j<n;j++)	  
		B.a[i*n+j]=rand()%10;
}
void PrintOut(Array A)
{  
	int n=A.n;
	int i,j;
	for(i=0;i<n;i++)
	   { for(j=0;j<n;j++)
		   cout<<A.a[i*n+j]<<' ';
		 printf("\n");	
	   }
}
void divide(Array d,Array d00,Array d01,Array d10,Array d11)  /*分割矩阵*/
{
	int n=d00.n;
   int i,j;
   for(i=0;i<n;i++)
   {
	   for(j=0;j<n;j++)
	   {
		   d00.a[n*i+j]=d.a[2*n*i+j];
		   d01.a[n*i+j]=d.a[2*n*i+n+j];
		   d10.a[n*i+j]=d.a[2*n*n+2*n*i+j];
		   d11.a[n*i+j]=d.a[2*n*n+2*n*i+n+j];
	   }
   }
}
Array merge(Array d00,Array d01,Array d10,Array d11)  
{
  int n=d00.n;
  int i,j;
  Array d;
  d.a=(int *)malloc(sizeof(int)* (4*n*n));
  for(i=0;i<n;i++)
   {
	   for(j=0;j<n;j++)
	   {
		   d.a[2*n*i+j]=d00.a[n*i+j];
		   d.a[2*n*i+n+j]=d01.a[n*i+j];
		   d.a[2*n*n+2*n*i+j]=d10.a[n*i+j];
		   d.a[2*n*n+2*n*i+n+j]=d11.a[n*i+j];
	   }
   }
  d.n=2*n;
  return d;
}
Array operator +(Array A,Array B)
{
	int n=A.n;
	Array C;
	C.a=(int *)malloc(sizeof(int)*(n*n));
	for(int i=0;i<n*n;i++)
		C.a[i]=A.a[i]+B.a[i];
	C.n=A.n;
	return C;
}
Array operator -(Array A,Array B)
{
	int n=A.n;
	Array C;
	C.a=(int *)malloc(sizeof(int)*(n*n));
	for(int i=0;i<n*n;i++)
		C.a[i]=A.a[i]-B.a[i];
	C.n=A.n;
	return C;
}
Array strassen(Array A,Array B) 
{  
  int n=A.n;
  Array C;
  C.a=(int *)malloc(sizeof(int)*(n*n));
  C.n=n;
  if(n==2)
  {
	int m1,m2,m3,m4,m5,m6,m7;
    m1=(A.a[0]+A.a[3])*(B.a[0]+B.a[3]);
    m2=(A.a[2]+A.a[3])*B.a[0];
    m3=A.a[0]*(B.a[1]-B.a[3]);
    m4=A.a[3]*(B.a[2]-B.a[0]);
    m5=(A.a[0]+A.a[1])*B.a[3];
    m6=(A.a[2]-A.a[0])*(B.a[0]+B.a[1]);
    m7=(A.a[1]-A.a[3])*(B.a[2]+B.a[3]);
    C.a[0]=m1+m4-m5+m7;
    C.a[1]=m3+m5;
    C.a[2]=m2+m4;
    C.a[3]=m1+m3-m2+m6;
    return C;
  }
else
  {
    n=n/2; 
	Array a00,a01,a10,a11;
    Array b00,b01,b10,b11; 
	Array c00,c01,c10,c11;
    Array s1,s2,s3,s4,s5,s6,s7; 
    a00.a=(int *)malloc(sizeof(int)* (n*n));
	a00.n=n;
    a01.a=(int *)malloc(sizeof(int)* (n*n));
	a01.n=n;
    a10.a=(int *)malloc(sizeof(int)* (n*n));
	a10.n=n;
    a11.a=(int *)malloc(sizeof(int)* (n*n));
	a11.n=n;
    b00.a=(int *)malloc(sizeof(int)* (n*n));
	b00.n=n;
    b01.a=(int *)malloc(sizeof(int)* (n*n));
	b01.n=n;
    b10.a=(int *)malloc(sizeof(int)* (n*n));
	b10.n=n;
    b11.a=(int *)malloc(sizeof(int)* (n*n));
	b11.n=n; 
    divide(A,a00,a01,a10,a11);
    divide(B,b00,b01,b10,b11); 
	s1=strassen(a00+a11,b00+b11);
	s2=strassen(a10+a11,b00);
    s3=strassen(a00,b01-b11);
    s5=strassen(a00+a01,b11);   
    s4=strassen(a11,b10-b00);    
    s6=strassen(a10-a00,b00+b01);
    s7=strassen(a01-a11,b10+b11); 
    c00=s1+s4-s5+s7;
    c01=s3+s5;
    c10=s2+s4;
    c11=s1+s3-s2+s6; 
    C=merge(c00,c01,c10,c11);
    return C;
  }
}
Array mul(Array A,Array B)  //普通的矩阵乘法计算
{
	int n=A.n;
	Array C;
	C.a=(int *)malloc(sizeof(int)*(n*n));
	C.n=n; 
    int i,j,k;
    for(i=0;i<n;i++)
        for(j=0;j<n;j++)
        {    
            C.a[i*n+j]=0;
            for(k=0;k<n;k++)
            C.a[i*n+j]=C.a[i*n+j]+A.a[i*n+k]*B.a[k*n+j];
        }
	return C;
}
void matrix()
{   
	int n;
	char ch;
	Array A,B,C;
	
	printf("\t\t计算M1×M2 的乘积\n");
	printf("\t\t输入矩阵阶数n:");
	scanf("%d",&n); 
    A.a=(int *)malloc(sizeof(int)* (n*n));
	A.n=n;
    B.a=(int *)malloc(sizeof(int)* (n*n));
	B.n=n;
    C.a=(int *)malloc(sizeof(int)* (n*n));
    C.n=n; 
    printf("\t\t---1 手动输入---\n");
    printf("\t\t---2 随机生成---\n");
    printf("\t\t请选择\n\n");
    ch=getch();
	switch(ch)
	   {
	   case '1':
	           printf("手动输入\n");
			   PrintIn(A,B);			   
			   printf("\n");
			   break;
	   case '2':
		           printf("自动生成\n");
				   
				   RandomIn(A,B);				   
				   			   
				   break;
	   default:
				printf("按键错误\n");break;
	   }
	   printf("结果数组A中数据为:\n");
	   PrintOut(A);
	   printf("结果数组B中数据为:\n");
	   PrintOut(B);
	   cout<<endl; 
	   do
	   {
		   double start, finish,duration; 
		   printf("\n---1 用BF方法---\n");
		   printf("---2 用DAC方法---\n");
		   printf("---3   退出 ---\n");
		   printf("\n请选择:");
		   ch=getch();
		   switch(ch)
		   {
		   case '1': 
			   start = clock();
			   C=mul(A,B);
			   finish = clock();
			   duration = (double)(finish - start); 
			   printf("\n用BF方法得出的结果\n");
			   PrintOut(C);
			   printf( "用BF方法计算矩阵所花费的时间是:%f ms\n", duration );
			   printf("\n");break;
		   case '2':
 			   start = clock();
			   C=strassen(A,B);
			   finish = clock();
			   duration = (double)(finish - start); 
			   printf("用DAC方法得出的结果\n");
			   PrintOut(C);
			   printf( "DAC方法计算矩阵所花费的时间是:%f ms\n", duration );
			   printf("\n");break;
		   case '3':
       			exit(0);
		   default:
			   printf("按键错误\n");
	   }
		   printf("\n 你想用另外一种方法吗?请输入(Y/N)?:");
		   do
		   {
			   ch=getchar();
		   }while(ch!='Y'&&ch!='y'&&ch!='N'&&ch!='n');
	   }while(ch=='Y'||ch=='y');
}



//硬币算法实现阶段
void print(int jia, int zhen, int i)
{
	if(jia > zhen)
	{
		cout<<"位置在:"<<(i + 1)<<"是假币!"<<"且偏重!";
	}
	else {
		cout<<"位置在:"<<(i + 1)<<"是假币!"<<"且偏轻!";
	}
}
void compare(int a, int b,int real, int index1,int index2)
{
	if(a == real)
	{
		print(b,real,index2);
	}
	else
	{
		print(a, real,index1);
	}
}
void eightcoin(int arr[])
{
	//1. 取数组中的前6个元素分为两组进行比较abc,def
	//会有a+b+c > d+e+f | a+b+c == d+e+f | a+b+c < d+e+f 三种情况
	int abc = arr[0] + arr[1] + arr[2];
	int def = arr[3] + arr[4] + arr[5];
	int a = arr[0];
	int b = arr[1];
	int c = arr[2];
	int d = arr[3];
	int e = arr[4];
	int f = arr[5];
	int g = arr[6];
	int h = arr[7];
	if(abc > def)		//6枚硬币必有一枚假币,g,h为真币
	{
		if((a + e) > (d + b))	//去掉c,f,且b,e互换后,没有引起天平变化,说明假币必然是a,d中的一个
		{
			compare(a, d, g,1,3);
			
		}
		else if((a + e) == (d + b))
		{
			compare(c,f,g,2,5);
		}
		else
		{
			compare(b,e,g,1,4);
		}
	}
	else if(abc == def)	//假币在g,h之中,最好状态
	{
		
		if(g == a)
		{
			print(h,g,7);
		} 
		else
		{
			print(g,h, 6);
		}
 
	}
	else				//abc < def 这两组存在一枚假币,g,h为真币
	{
		if((a + e) > (d + b))
		{
			compare(b,e,g,1,4);
		}
		else if((a + e) == (d + b))
		{
			compare(c,f,g,2,5);
		}
		else
		{
			compare(a, d, g,1,3);
		}
	}
 
}
void yingbi()//主函数 
{
	cout<<"实验3"<<endl; 
	int i = 0;
	int arr[8];
	//这里输入a、b、c、d、e、f、g、h的重量
	cout<<"请输入八枚硬币:"<<endl;
	for(i; i < 8; i++)
	{
		cin>>arr[i];
	}
	eightcoin(arr);
	
}

//堆排序
void in(int h[N],int n)
{
	int i;
	printf("手动输入要排序的数:");
	for(i=1;i<=n;i++)
		scanf("%d",&h[i]);
}
void random(int h[N],int n)
{
	int i;
    for(i=1;i<=n;i++)
		h[i]=rand();
    printf("随机产生要排序的数如下所示:\n");
    for(i=1;i<=n;i++)
        printf("%d\t",h[i]);
	printf("\n\n");
}
//自底向上构造一个堆
void HeapBottomUp(int h[],int n)
{
	int heap,i,k,v,j; 
	for(i=(n/2);i>0;i--)
	{
		k=i;
	    v=h[k];
        heap=0;
	    while((heap==0)&&(2*k<=n))
		{
			j=2*k;
			if(j<n)
			{
				if(h[j]<h[j+1])
		        j=j+1;
			}
			if(v>h[j])
				heap=1;
			else
			{
				h[k]=h[j];
				k=j;
				h[k]=v;
			}
		}
	}
}
void HEAP()
{
	int h[N]={0},i,n,elem,m;
    double start, finish;
    char ch=' ';
    printf("\n\t\t输入要排序的数的规模:");
	scanf("%d",&n);
    printf("\n---1 手动输入---\n");
    printf("---2 自动生成---\n");
    printf("请选择:");
	do{
		ch=getch();
		if(ch=='1')
			in(h,n);
		if(ch=='2')
			random(h,n);
		else
			printf("\n输入出错,请重输:");
	}while(ch!='1'&&ch!='2');
	start=clock();
	m=n;
	while(m>1)
	{
	     HeapBottomUp(h,m);
	     //for(i=1;i<=n;i++)
			 //printf("%d\t\t",h[i]);
		 //printf("\n");
		 //根键(最大)与堆中最后一个键交换
         elem=h[1];
	     h[1]=h[m];
	     h[m]=elem;
         m=m-1;//堆的规模减一
         //for(i=1;i<=n;i++)
			 //printf("%d  ",h[i]);
         //printf("\n");
	}
	finish=clock();
	printf("\n输出排好的数组元素:\n");
    for(i=1;i<=n;i++)
	  printf("%d\t",h[i]);
	printf("\n输出算法执行的时间%f ",finish-start);
}


// 全源最短路径
void CreateGraph(AdjMatrix *G) //图的生成函数
{ 
    int n,e,vi,vj,w,i,j,choice,ret,k;
    FILE *fp;
    
	printf("请选择数据输入方式\n");
	printf("1.手动输入\n");
 	printf("2.自动输入\n"); 
    ret = scanf("%d",&choice); 
    
    while(ret != 1)
	{
		cout<<"您的输入有误,请重新输入!"<<endl;
		fflush(stdin);
		ret = scanf("%d",&choice);
	}
	
	if(choice == 2)
	{
  		n=rand()%10;
		  e=rand()%10;
		  //cout<<n<<"   "<<e<<endl;
   		G->numV=n;G->numE=e;
   		for(i=0;i<n;i++) //图的初始化
     	{
		    for(j=0;j<n;j++)
            { 
         	   if(i==j)
             	   G->Edge[i][j]=0;
          	  else 
           	     G->Edge[i][j]=32767;
            }
         } 
   		 for(i=0;i<n;i++)
   		 { 
       	 	for(i=0;i<G->numV;i++) //将顶点存入数组中
       		 { 
      		  //printf("请输入第%d个顶点的信息(整型):",i+1);  
     		 
     		   G->Vertices[i]=rand();
     		  // printf("第%d个顶点的信息(整型):%d",i+1,G->Vertices[i]);
      	 	 }
      	 } 
   		 printf("\n");

    	for(i=0;i<G->numE;i++)
   	    { 
       	   //printf("请输入边的信息i,j,w(以空格分隔):");
       	   vi=rand()%10;vj=rand()%10;w=rand()%10;
    		//printf("%d  %d  %d\n",vi,vj,w);
      	   //若为不带权值的图,则w输入1
           //若为带权值的图,则w输入对应权值

       	   G->Edge[vi][vj]=w;//①
      	   G->Edge[vj][vi]=w;//②
           //无向图具有对称性的规律,通过①②实现
           //有向图不具备此性质,所以只需要①
   		}
	}
	else
	{
		printf("请输入图的顶点数和边数(以空格分隔):");
  			scanf("%d%d",&n,&e);
   		G->numV=n;G->numE=e;
   		for(i=0;i<n;i++) //图的初始化
     	{
		    for(j=0;j<n;j++)
            { 
         	   if(i==j)
             	   G->Edge[i][j]=0;
          	  else 
           	     G->Edge[i][j]=32767;
            }
         } 
   		 for(i=0;i<n;i++)
   		 { 
       	 	for(i=0;i<G->numV;i++) //将顶点存入数组中
       		 { 
      		  printf("请输入第%d个顶点的信息(整型):",i+1);  
     		 // G->adjlist[i].vertex=getchar(); 
     		   scanf(" %d",&G->Vertices[i]);
      	 	 }
      	 } 
   		 printf("\n");

    	for(i=0;i<G->numE;i++)
   	    { 
       	   printf("请输入边的信息i,j,w(以空格分隔):");
     	   scanf("%d%d%d",&vi,&vj,&w); 
      	   //若为不带权值的图,则w输入1
           //若为带权值的图,则w输入对应权值

       	   G->Edge[vi][vj]=w;//①
      	   G->Edge[vj][vi]=w;//②
           //无向图具有对称性的规律,通过①②实现
           //有向图不具备此性质,所以只需要①
   		}
	}
}
void DispGraph(AdjMatrix G) //输出邻接矩阵的信息
{ 
    int i,j;
    printf("\n输出顶点的信息(整型):\n");
    for(i=0;i<G.numV;i++)
    {
       printf("%8d",G.Vertices[i]);
	}
	
	
    printf("\n\n\n输出邻接矩阵:\n");
    printf("\t");
    for(i=0;i<G.numV;i++)
        printf("%8d",G.Vertices[i]);

    for(i=0;i<G.numV;i++)
    { 
        printf("\n%8d",i);
        for(j=0;j<G.numV;j++)
        { 
        if(G.Edge[i][j]==32767) 
        //两点之间无连接时权值为默认的32767,但输出时为了方便输出 "∞"
            printf("%8s", "∞");
        else
            printf("%8d",G.Edge[i][j]);
        }
        printf("\n");   
    }
}
void Ppath(int path[][MaxVertices],int i,int j)
{
    int k;
    k=path[i][j];
    if (k==-1)
    {
        return;
    }

    Ppath(path,i,k);
    printf("%d->",k);
    Ppath(path,k,j);
}

void Dispath(int A[][MaxVertices],int path[][MaxVertices],int n)
{
    int i,j;
    for (i=0;i<n;i++)
    {
        for (j=0;j<n;j++)
        {
            if (A[i][j]==INF)
            {
                if (i!=j)
                {
                    printf("从%d到%d没有路径\n",i,j);
                }
            }
            else
            {
                printf("  从%d到%d的最短路径长度为:%d ",i,j,A[i][j]);
                printf("路径:%d->",i);

                Ppath(path,i,j);//两点i,j之间还有其他中继结点,则循环套用次函数
                printf("%d\n",j);
            }
        }
    }
}
void Floyd(AdjMatrix *G)
{
    int A[MaxVertices][MaxVertices],path[MaxVertices][MaxVertices];
    int i,j,k;
    //初始化
    for (i=0;i<G->numV;i++)
    {
        for (j=0;j<G->numV;j++)
        {
            A[i][j]=G->Edge[i][j];
            path[i][j]=-1;
        }
    }
//三重循环,floyd算法核心
    for (k=0;k<G->numV;k++)
    {
        for (i=0;i<G->numV;i++)
        {
            for (j=0;j<G->numV;j++)
            {
                if (A[i][j]>A[i][k]+A[k][j])
                {
                    A[i][j]=A[i][k]+A[k][j];
                    path[i][j]=k;
                }
            }
        }
    }
    Dispath(A,path,G->numV);//输出函数
}

void exit()
{
	cout<<"程序运行结束,窗口即将关闭!"<<endl;
	 system("pause");
}

void select ()//主菜单选择函数 
{
	AdjMatrix G;
	int n;
	cout<<"请输入:";
	cin>>n;
	//输入菜单数字判断 
	switch(n)
	{
		case 1:fibonacci();
		break;
		case 2:matrix();
		break;
		case 3:yingbi();
		break;
		case 4:HEAP(); 
		break;
		case 5:
				 CreateGraph(&G);
    			 Floyd(&G);
    			 DispGraph(G);
		break;
		case 99:exit();
		break;
		default :
			cout<<"输入错误"; 
			menu();
			select();
		
	}
}

int main(void)
{	
	int m =1;//控制菜单,始终进入 
	while (m == 1)
	{
			menu();
			select();
			cout<<endl; 
			cout<<"				是否继续?   继续请输入:1  不继续请输入:0 			"<<endl;
			cout<<endl; 
			cin>>m;
			system("cls");
	}
	
}


实验界面

posted @ 2019-12-11 21:19  北忘山  阅读(123)  评论(0编辑  收藏  举报