请查看:
算法分析文章
#include
#include
#include
#include
#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");
}
}