当前位置:文档之家› 关键路径

关键路径

一.实验名称:关键路径二.实验目的:1.熟悉图的存储结构2.掌握求关键路径的算法3.了解实际问题的求解效率与采用何种存储结构和算法有密切关系三.程序#include "stdio.h"#include "malloc.h"//-----图的邻接表存储结构-----typedef struct ArcNode{ //弧结点int adjvex; //该弧指向的顶点的序号struct ArcNode *nextarc; //指向下一条弧的指针int info; //该弧相关信息的指针}ArcNode,*Arc;typedef struct VNode{ //顶点char data; //顶点信息ArcNode *firstarc; //指向第一条依附该顶点的弧}VNode,AdjList[20];typedef struct{ //图AdjList vertices; //存储图的顶点的数组int vexnum,arcnum; //图的当前定点数和弧数}ALGraph;typedef struct{ //栈int *base,*top; //栈底和栈顶指针int stacksize; //栈的长度}SqStack;void CreateG(ALGraph &G,int m) //建顶点数为m的图{int i,j,k,w; Arc p,q;G.vexnum=m;G.arcnum=0; //对图进行初始化for(i=0;i<m;i++) //输入m个顶点的信息{printf("\nplease input VNode%d data:",i);scanf("%c",&G.vertices[i].data);}for(i=1;i<=m;i++) //给各顶点连以其为尾的弧{printf("\nplease input VNode%d outarc:",i);scanf("%d",&j); //输入该顶点第一条弧指向的顶点在存储数组中的序号if(!j) G.vertices[i-1].firstarc=NULL; //j=0该顶点没有以其为尾的弧else{ G.arcnum++; //弧数增加1p=(Arc)malloc(sizeof(ArcNode)); //为该顶点开辟第一个弧结点p->adjvex=j-1; //该弧指向的顶点序号G.vertices[i-1].firstarc=p; //把弧连到该顶点for(;;) //建立该顶点的其他以其为尾的弧结点{scanf("%d",&k);if(!k) {p->nextarc=NULL;break;}else{G.arcnum++;q=(Arc)malloc(sizeof(ArcNode));q->adjvex=k-1;p->nextarc=q; //前一条弧指向后一条弧}}}}//所有弧结点建立完毕for(i=1;i<=m;i++) //分别输入每个顶点以其为尾的弧的信息{printf("\nplease input arcs'information of VNode%d:",i);p=G.vertices[i-1].firstarc;while(p){scanf("%d",&w);p->info=w;p=p->nextarc;}}printf(“\n”);}void FindInDegree(ALGraph G,int*indegree)//求图G各顶点的入度,存入数组indegree中,序号对应于顶点序号{int i;Arc p;indegree=(int *)malloc(G.vexnum*sizeof(int));for(i=0;i<G.vexnum;i++) //indegree[ ]初始化indegree[i]=0;for(i=1;i<=G.vexnum;i++){p=G.vertices[i-1].firstarc; //p指向弧结点while(p){indegree[p->adjvex]++; //通过弧结点储存的指向的顶点序号求各顶点入度p=p->nextarc;}}}void InitStack(SqStack &S) //构建一个空栈S {S.base=(int *)malloc(20*sizeof(int));S.top=S.base;S.stacksize=20;int StackEmpty(SqStack S) //若栈S为空,则返回1,否则0 {if(S.base==S.top) return 1;else return 0;}int Pop(SqStack &S,int &e) //删除S的栈顶元素,并用e返回其值{if(S.top==S.base) return 0;e=*--S.top; return 1;}void Push(SqStack &S,int e) //插入元素e为新的栈顶元素{*S.top++=e;}int TopologicalOrder(ALGraph G,SqStack &T,int ve[ ])//T为拓扑序列顶点栈,S为零入度顶点栈//若G无回路,则用栈T返回G的一个拓扑序列,且函数值为1,否则为0{int i,j,k,*indegree,count; Arc p; SqStack S;FindInDegree(G,indegree); //对各顶点求入度InitStack(S); //建零入度栈for(i=0;i<G.vexnum;i++){if(!indegree[i]) Push(S,i);}InitStack(T); count=0;for(i=0;i<G.vexnum;i++) //初始化ve[i]=0;while(!StackEmpty(S)){Pop(S,j); Push (T,j); ++count; //j号顶点如T栈并计数for(p=G.vertices[j].firstarc; p; p=p->nextarc)k=p->adjvex; //对j号顶点的每个邻接点的入度减1 if(--indegree[k]==0) Push(S,k); //若入度为0,则如栈if(ve[j]+p->info>ve[k]) ve[k]=ve[j]+p->info;}if(count<G.vexnum) return 0; //该有向网有回路else return 1;}int CriticalPath(ALGraph G) //G为有向网,输出G的各项关键活动{int j,k,dut,ee,el,vl[20],ve[20]; char tag; SqStack T;Arc p;if(!TopologicalOrder(G,T,ve)) return 0;for(j=0;j<G.vexnum;j++) //初始化顶点时间的最迟发生时间vl[j]=ve[j];while(!StackEmpty(T)) //按拓扑排逆序求各顶点的v1值for(Pop(T,j),p=G.vertices[j].firstarc;p;p=p->nextarc){k=p->adjvex; dut=p->info; //活动持续时间dut<j,k>if(vl[k]-dut<vl[j]) vl[j]=vl[k]-dut;printf(“\nThe result is:\n”)for(j=0; j<G.vexnum; ++j) //求ee,el和关键活动for(p=G.vertices[j].firstarc; p; p=p->nextarc){k=p->adjvex; dut=p->info;ee=ve[j];el=vl[k]-dut;tag=(ee==el)?'*':' ';printf("dut<%c,%d>=%,ee=%d,el=%3d:%c\n",G.vertices[j].data,G.vertices[k].data,dut,ee,el,tag);//输出关键活动}return 1;}void main(){ALGraph G; int m;printf("please input the number of VNode:");scanf("%d",&m); //输入图的顶点数CreateG(G,m); //创建图CriticalPath(G); //求关键路径}四.运行结果1.输入2.输出一.实验名称:比较3种排序方法的效率二.实验目的1.深刻理解排序的定义和各种排序方法的特点2.了解各种方法的排序过程极其依据的原则3.掌握排序的算法三.程序#include "stdio.h"#include "stdlib.h"#include "time.h"#define swap(x,y) {int t;t=x;x=y;y=t;}long steps1=0,steps2=0,steps3=0; //steps记录排序运行步骤//-----------选择排序-----------int SelectMin(int r[ ],int i) //在r[i…10000]中选择最小的数并返回{int min,j;for(j=min=i;j<=10000;j++)if(r[j]>r[j+1]) min=j+1; steps1=steps1+10001-i;return min;}void Selection(int r[ ]) //选择排序主函数{int i,j;for(i=1;i<10000;++i,steps1++) //选择第小的记录,并交换到位{j=SelectMin(r,i);if(i!=j) swap(r[i],r[j]); //与第个记录交换}}//------------快速排序----------int Partition(int r[ ],int low,int high) //交换r[low…high]的记录,使枢纽记录到位,并返回其所、//在位置,此时在它之前(后)的记录均不大(小)于它{int pivot;r[0]=r[low]; //子用数组的第一个记录作枢纽记录pivot=r[low]; //枢轴记录关键字steps2=steps2+2;while(low<high) //从数组的两端交替的向中间扫描{while(low<high&&r[high]>=pivot) {--high; steps2++;}r[low]=r[high]; steps2++; //将比枢轴记录小的记录交换到低端while(low<high&&r[low]<=pivot) {++low;steps2++;}r[high]=r[low];steps2++; //将比枢轴记录大的记录交换到高端}r[low]=r[0]; steps2++; //枢轴记录到位return low; //返回枢轴所在位置}void QSort(int r[],int low,int high) //对子序r[low…high]作快速排序{int pivotloc;if(low<high) //长度大于1{pivotloc=Partition(r,low,high); //将r[low…high]一分为二QSort(r,low,pivotloc-1); //对子表递归排序,pivotloc是枢轴位置QSort(r,pivotloc+1,high); //对高子表递归排序}steps2=steps2+3;}void Quick(int r[ ]) //快速排序主函数{QSort(r,1,1000);}//------------堆排序-------------void Heap(int r[ ],int i,int m) //调整r[i…m]成大顶堆{ int j,x;x=r[i];j=2*i; steps3=steps3+2;while(j<=m) //沿r[i]较大的孩子结点往下筛选{ if(j<m)if(r[j]>r[j+1]){ j++;steps3++;} //j为r[i]较大记录的下标if(r[j]<x){r[i]=r[j];i=j;j=2*i; steps3=steps3+3;}else{ j=m+1; steps3++;}}r[i]=x;steps3++; //插入}void Heaping(int r[ ],int n) //对含n个数进行堆排序{int i,v,x;for(i=n;i>0;i--,steps3++)r[i]=r[i-1];for(i=n/2;i>=1;i--,steps3++) //把r[n]建成大顶堆Heap(a,i,n);for(v=n;v>=2;v--) //将堆顶记录和当前未经排序子序列r[1…v] { x=r[1]; //中最后一个记录相互交换r[1]=r[v];r[v]=x;Heap(r,1,v-1);steps3=steps3+4; //将r[1…v-1]重新调整成大顶堆}for(i=0;i<n;i++,steps3++)r[i]=r[i+1];}void main(){int r1[10001],r2[10001],r3[10001],i;randomize(); //随机产生10000个不相同的数,存入数组中for(i=1;i<=10000;i++)r1[i]=r2[i]=r3[i]=random(100)+1;Selection(r1); //选择排序Quick(r2); //快速排序Heaping(r3,10000); //堆排序printf("steps1=%ld,steps2=%ld,steps3=%ld\n",steps1,steps2,steps3);} //打印三个排序的总步骤数四.运行结果结论:快速排序效率最高,其次是堆排序,选择排序效率较低。

相关主题