当前位置:文档之家› 计算机算法基础实验报告

计算机算法基础实验报告

课程实验报告题目:计算机算法基础课程实验课程名称:计算机算法基础专业班级:计算机科学与技术班学号:姓名:指导教师:报告日期:2012年11月5日计算机科学与技术学院题目1、比较快速分类算法和归并分类算法时间效率一、方案设计本实验要求比较快速分类算法和归并分类算法的效率,于是我们很容易联想到通过对比两种算法在处理相同数据所使用的时间来比较两种算法的时间效率。

因此先定义一个函数random()来生成设定个数个随机数,并以文件形式输出。

快速分类算法和归并分类算法均使用文件形式读入数据并以文件形式输出分类结果,中间过程没有人工参与,这就保证了程序运行时间基本和分类时间一致,因此算法所用时间根据调试窗口所给出程序运行时间为准。

试验中快速分类算法和归并分类算法分别在不同的工程文件中实现,对于不同个数的数据分次测试。

为了使两种算法更具有可比性,两种算法都使用递归方法实现。

已知快速分类算法和归并分类算法的平均情况时间都是O(nlogn),但是最坏情况下快速分类算法算法时间复杂度为O(n2),而归并分类算法的时间下界为Ω(nlogn),因此在比较了两种算法在一般情况下的时间效率之后还要比较两种算法在最坏情况下的时间效率。

快速分类算法的最坏情况为被分类数据有序。

二、方案实现随机数据生成:#include <stdio.h>#include <stdlib.h>#include <time.h>#define MAX 40000 //生成数据个数,根据不同要求改变int main(){int a[MAX]; //整形数组a[MAX]存放生成的随机数long i;memset(a,0,sizeof(a));FILE *fp;fp = fopen("example.txt","wt");srand((int)time(0));for(i=0; i<MAX; i++){a[i] = rand()%40000; //生成小于40000的随机数}for(i=0; i<MAX; i++)fprintf(fp, "%d ", a[i]); //将数据写入文件fclose(fp);return 0;}快速分类算法:#include <stdio.h>#include <stdlib.h>#define MAX 40000 //分类数据个数,根据不同要求改变int Partition(int *R,int i,int j){int pivot=R[i]; //R[i]是划分元素while(i<j){while(i<j&&R[j]>=pivot) //j由右向左移j--;if(i<j)R[i++]=R[j];while(i<j&&R[i]<=pivot) //i由左向右移i++;if(i<j)R[j--]=R[i];}R[i]=pivot;return i; //返回划分元素的最终位置}void QuickSort(int *R,int low,int high){int pivotpos;if(low<high){pivotpos=Partition(R,low,high);QuickSort(R,low,pivotpos-1);QuickSort(R,pivotpos+1,high);}}int main(){FILE *fp;int a[MAX],i,n;fp = fopen("example.txt","rt");for(i=0; i<40000; i++)fscanf(fp, "%d ", &a[i]); //从文件中读入数据QuickSort(a, 0, MAX-1); //快速分类fclose(fp);fp = fopen("result.txt","wt");for(i=0; i<MAX; i++)fprintf(fp, "%d ", a[i]); //排序后数据写入文件fclose(fp);return 0;}归并分类算法:#include <stdio.h>#include <stdlib.h>#define MAX 40000 //分类数据个数,根据不同要求改变int A[MAX];void MERGE(int low,int mid,int high) //归并组合{int h,k,i,j;int B[MAX]; //组合比较后形成新的数组h=low;i=0;j=mid+1; //对h,i,j分别初始化while(h<=mid&&j<=high){if(A[h]<=A[j]){B[i]=A[h]; //部分归并后将小的数放进新的数组h++;}else{B[i]=A[j];j++;}i++;}while(h<=mid)B[i++]=A[h++]; //转存剩余元素while(j<=high)B[i++]=A[j++];for(i=0,k=low;i<=high-low;i++,k++)A[k]=B[i]; //将B数组中的所有元素还回到A数组中}void MERGESORT(int low,int high)//归并排序{int mid;if(low<high){mid=(high+low)/2; //查找中点位置MERGESORT(low,mid); //前部分排序MERGESORT(mid+1,high); //后部分排序MERGE(low,mid,high);}}int main(){FILE *fp;int i,n;fp = fopen("example.txt","rt");for(i=0; i<MAX; i++)fscanf(fp, "%d ", &A[i]); //从文件中读入数据MERGESORT(0, MAX-1); //归并分类排序fclose(fp);fp = fopen("result.txt","wt");for(i=0; i<MAX; i++)fprintf(fp, "%d ", A[i]); //结果写入文件fclose(fp);return 0;}三、结果分析实验测试数据为小于40000的整形随机数,一般情况下数据是无序排列的,实验中分使用个数为40000,50000,60000,70000,80000,160000,320000的不同数据测试算法运行时间,得到结果如下:(时间单位:ms)算法运行时间图:最坏情况下测试结果:(时间单位:ms)由测试结果可以看出,在一般情况下快速分类算法时间效率要优于归并分类算法,尤其是当数据量变大时归并分类算法花费时间有较大增长,而快速分类算法基本呈线性增长。

在最坏请况下快速分类算法优势不再,花费时间很多,而归并分类算法花费时间与一般情况下基本持平,可见归并分类算法与数据的顺序与否没有关系,这也说明了归并分类算法算法是最坏情况下的最优解。

题目2、修改算法SHORTEST-PATHS,使得它在获取最短路径的同时还得到这些路径。

一、方案设计图的信息存放在文件中,通过文件读入图的信息。

文件中信息存储格式为:第一个整数表示顶点数,第二个整数表示边个数,下面每三个整数为一组,表示单条边的信息,每组中第一个数为该条边的起点,第二个数为终点,第三个数是边的权值。

设定全局变量n表示结点个数,数组s存放已被选中的结点,数组dist[i]是从v0开始只经s中的结点而在i结束的那条最短路径的长度。

二维数组a记录的是成本邻接矩阵,pre记录最短路径到i的前一个顶点,用于最后最短路径的输出。

在主函数中首先进行成本邻接矩阵的初始化,由输入得到结点个数和有向图的边边的权值,接下来输入一个起始节点v,再通过dijkstra算法找到最短路径生成树并将最短路径信息保存在pre中,最后输出各条最短路径。

dijkstra函数第一个for循环先将从源点到i的最短路径设为从源点到i的权值,集合s初始化为空,从源点到i有通路时最短路径前一个节点设为源点。

第二个for循环中嵌套的第一个for循环选取结点u使得dist[u]=min{dist[w]},第二个嵌套循环将所有s[w]=0的结点修改距离使得dist[w]=min{dist[w],dist[w]+a[u][w]}。

二、方案实现#include <stdio.h>#include <stdlib.h>#define N 10#define INFINITY 32767 //无穷大int number=0; //节点数int A[N][N]; //记录边的权值int dist[N]; //v0开始只经s中的结点而在i结束的那条最短路径的长度int pre[N]; //最短路径到i的前一个顶点int s[N+1]; //已被选中的结点int path[N+1]; //路径void Init(){FILE *fp;int i,j,w,n;memset(A, 0, sizeof(A));fp = fopen("relation.txt", "rt");fscanf(fp, "%d\n", &number); //从文件中读入节点数fscanf(fp, "%d\n", &n); //从文件中读入边条数for(; n>0; n--){fscanf(fp, "%d %d %d\n", &i,&j,&w); //读入边信息A[i][j] = w; //图的信息存入成本邻接矩阵}for(i=1; i<=number; i++)for(j=1; j<=number; j++){if(A[i][j]==0)A[i][j] = INFINITY; //不可到达的边权值为无穷大if(i == j)A[i][j] = 0; //矩阵对角线为0}fclose(fp);}void dijkstra(int qidian){int i,j,u,temp;long newdist; //当前路径长度if(qidian<1 || qidian>number)return;for(i=1;i<=number;i++) //初始设置{dist[i]=A[qidian][i];//初始时从源点到i的最短路径设为从源点到i的权值s[i]=1;if(dist[i]==INFINITY)pre[i]=0; //从源点到i没有通路elsepre[i]=qidian;//从源点到i有通路时,最短路径前一个结点设为源点}dist[qidian]=0; //源点到源点的最短路径为0s[qidian]=0;for(i=1;i<number;i++) //中心部分{temp=INFINITY;u=qidian;//找出一个剩余结点中到源点最短的结点for(j=1;j<=number;j++)//如果该点不是源点并且源点到j点路径是最短if((s[j]==1) && (dist[j]<temp)){u=j; //u记录最短路径的点temp=dist[j]; //记录源点到j点的最短路径}s[u]=0; //u点是下面进行比较的点for(j=1;j<=number;j++) //找出通过U点是否有更短的路径//源点到u的路径+u到j的路径小于源点到j的路径if((s[j]==1) && (A[u][j]<INFINITY)){newdist=dist[u]+A[u][j];if(newdist<dist[j]){dist[j]=newdist; //更改源点到j的路径长度pre[j]=u;//更改源点到j的最短路径中,j的前一个结点}}}}int main(){int qidian,i,j,n;printf("输入起点:");scanf("%d",&qidian);Init(); //初始化成本临界矩阵dijkstra(qidian);memset(path, 0, sizeof(path));for(i=1;i<=number;i++) //得到以起点为源点的每条最短路径并输出{if(i!=qidian && dist[i]<INFINITY){printf("\n从结点%d 到%d,最短路径长%d:\n",qidian,i,dist[i]);j=i;n=0;do{j=pre[j];path[n++]=j;} while(j!=qidian); //将逆序输出的点存入path数组n--;while(n>=0)printf("%d,",path[n--]); //顺序输出路径printf("%d",i);}}return 0;}三、结果分析程序运行结果:(有向图参照的是课本图5.10),图信息为7121 2 20 1 3 50 1 4 40 2 3 25 2 6 70 3 4 403 5 25 3 6 5045 55 56 10 57 70 6 7 501、起点选为1结点2、起点选为5可见程序得到了正确结果,在dijkstra函数中有两个for循环,第一个for循环时间复杂度为O(n),第二个for循环时间复杂度为O(n2)。

相关主题