求一个无向图G的连通分量的个数

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

《数据结构》实验报告实验内容:(一)判断一个图有无回路(二)求一个无向图G的连通分量的个数一、目的和要求(需求分析):1、了解图的定义和图的存储结构。2、熟悉掌握图的邻接矩阵和邻接表。3、理解图的遍历算法---深度优先搜索和广度优先搜索。4、学会编程处理图的连通性问题。二、程序设计的基本思想,原理和算法描述:(包括程序的结构,数据结构,输入/输出设计,符号名说明等)判断一个图有无回路:在程序设计中,先必须确定所要创建的图是有向还是无向,是图还是网,其次再根据各自的特点,用连接表来实现创建。在有向图中,先找出入度为0的顶点,删除与这个顶点相关联的边(出边),将与这些边相关的其它顶点的入度减1,循环直到没有入度为0的顶点。如果此时还有未被删除的顶点,则必然存在环路,否则不存在回路。无向图则可以转化为:如果存在回路,则必然存在一个子图,是一个回路。因此回路中所有定点的度=2。第一步:删除所有度=1的顶点及相关边,并将另外与这些边相关的其它顶点的度减1。第二步:将度数变为1的顶点排入队列,并从该队列中(使用栈)取出一个顶点,并重复步骤一。如果最后还有未删除的顶点,则存在回路,否则没有。求一个无向图G的连通分量的个数:用连接表创建图,对于非连通图,则需从多个顶点出发进行搜索,而每一次从一个新的起始点出发进行搜索过程中得到的顶点访问序列恰为其各个连通分量中的顶点集。所以在设计中,为了统计出无向图中的连通分量个数,则因在其深度优先所搜无向图时对函数DFSTraverse(ALGraphG)调用DFS次数进行统计,其结果便为无向图中连通分量个数。三、调试和运行程序过程中产生的问题及采取的措施:在调试和运行求一个无向图G的连通分量的个数程序时,由于执行语句块voidDFSTraverse(ALGraphG)先于voidDFS(ALGraphG,intv),而voidDFSTraverse(ALGraphG)内调用了DFS(),因此计算机无法正确运行,将两者顺序进行了交换,程序便实现了其功能,且运行正常。四、源程序及注释:判断一个图有无回路:#includestdio.h#includemalloc.h#includestdlib.h//输出有向图的一个拓扑序列。//图的邻接表存储表示#defineMAX_NAME3//顶点字符串的最大长度+1#defineMAX_VERTEX_NUM20#defineSTACK_INIT_SIZE10//存储空间初始分配量#defineSTACKINCREMENT2//存储空间分配增量typedefintInfoType;//存放网的权值typedefcharVertexType[MAX_NAME];//字符串类型typedefenum{DG,DN,AG,AN}GraphKind;//{有向图,有向网,无向图,无向网}typedefstructArcNode{intadjvex;//该弧所指向的顶点的位置structArcNode*nextarc;//指向下一条弧的指针InfoType*info;//网的权值指针)}ArcNode;//表结点typedefstructVNode{VertexTypedata;//顶点信息ArcNode*firstarc;//第一个表结点的地址,指向第一条依附该顶点的弧的指针}VNode,AdjList[MAX_VERTEX_NUM];//头结点typedefstruct{AdjListvertices;intvexnum,arcnum;//图的当前顶点数和弧数intkind;//图的种类标志}ALGraph;//若G中存在顶点u,则返回该顶点在图中位置;否则返回-1。intLocateVex(ALGraphG,VertexTypeu){inti;for(i=0;iG.vexnum;++i)if(strcmp(u,G.vertices[i].data)==0)returni;return-1;}//采用邻接表存储结构,构造没有相关信息的图G(用一个函数构造4种图)。intCreateGraph(ALGraph*G){inti,j,k;intw;//权值VertexTypeva,vb;ArcNode*p;printf(请输入图的类型(有向图:0,有向网:1,无向图:2,无向网:3):);scanf(%d,&(*G).kind);printf(请输入图的顶点数和边数:(空格)\n);scanf(%d%d,&(*G).vexnum,&(*G).arcnum);printf(请输入%d个顶点的值(小于%d个字符):\n,(*G).vexnum,MAX_NAME);for(i=0;i(*G).vexnum;++i)//构造顶点向量{scanf(%s,(*G).vertices[i].data);(*G).vertices[i].firstarc=NULL;}if((*G).kind==1||(*G).kind==3)//网printf(请顺序输入每条弧(边)的权值、弧尾和弧头(以空格作为间隔):\n);else//图printf(请顺序输入每条弧(边)的弧尾和弧头(以空格作为间隔):\n);for(k=0;k(*G).arcnum;++k)//构造表结点链表{if((*G).kind==1||(*G).kind==3)//网scanf(%d%s%s,&w,va,vb);else//图scanf(%s%s,va,vb);i=LocateVex(*G,va);//弧尾j=LocateVex(*G,vb);//弧头p=(ArcNode*)malloc(sizeof(ArcNode));p-adjvex=j;if((*G).kind==1||(*G).kind==3)//网{p-info=(int*)malloc(sizeof(int));*(p-info)=w;}elsep-info=NULL;//图p-nextarc=(*G).vertices[i].firstarc;//插在表头(*G).vertices[i].firstarc=p;if((*G).kind=2)//无向图或网,产生第二个表结点{p=(ArcNode*)malloc(sizeof(ArcNode));p-adjvex=i;if((*G).kind==3)//无向网{p-info=(int*)malloc(sizeof(int));*(p-info)=w;}elsep-info=NULL;//无向图p-nextarc=(*G).vertices[j].firstarc;//插在表头(*G).vertices[j].firstarc=p;}}return1;}voidDisplay(ALGraphG)//输出图的邻接表G。{inti;ArcNode*p;switch(G.kind){caseDG:printf(有向图\n);break;caseDN:printf(有向网\n);break;caseAG:printf(无向图\n);break;caseAN:printf(无向网\n);}printf(%d个顶点:\n,G.vexnum);for(i=0;iG.vexnum;++i)printf(%s,G.vertices[i].data);printf(\n%d条弧(边):\n,G.arcnum);for(i=0;iG.vexnum;i++){p=G.vertices[i].firstarc;while(p){if(G.kind=1)//有向{printf(%s→%s,G.vertices[i].data,G.vertices[p-adjvex].data);if(G.kind==DN)//网printf(:%d,*(p-info));}else//无向(避免输出两次){if(ip-adjvex){printf(%s-%s,G.vertices[i].data,G.vertices[p-adjvex].data);if(G.kind==AN)//网printf(:%d,*(p-info));}}p=p-nextarc;}printf(\n);}}voidFindInDegree(ALGraphG,intindegree[])//求顶点的入度。{inti;ArcNode*p;for(i=0;iG.vexnum;i++)indegree[i]=0;//赋初值for(i=0;iG.vexnum;i++){p=G.vertices[i].firstarc;while(p){indegree[p-adjvex]++;p=p-nextarc;}}}typedefintSElemType;//栈类型typedefstructSqStack//栈的顺序存储表示{SElemType*base;//在栈构造之前和销毁之后,base的值为NULLSElemType*top;//栈顶指针intstacksize;//当前已分配的存储空间,以元素为单位}SqStack;//顺序栈intInitStack(SqStack*S)//构造一个空栈S{//为栈底分配一个指定大小的存储空间(*S).base=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));if(!(*S).base)exit(0);//存储分配失败(*S).top=(*S).base;//栈底与栈顶相同表示一个空栈(*S).stacksize=STACK_INIT_SIZE;return1;}//若栈S为空栈(栈顶与栈底相同的),则返回1,否则返回0。intStackEmpty(SqStackS){if(S.top==S.base)return1;elsereturn0;}intPush(SqStack*S,SElemTypee)//插入元素e为新的栈顶元素。{if((*S).top-(*S).base=(*S).stacksize)//栈满,追加存储空间{(*S).base=(SElemType*)realloc((*S).base,((*S).stacksize+STACKINCREMENT)*sizeof(SElemType));if(!(*S).base)exit(0);//存储分配失败(*S).top=(*S).base+(*S).stacksize;(*S).stacksize+=STACKINCREMENT;}*((*S).top)++=e;//这个等式的++*优先级相同,但是它们的运算方式,是自右向左return1;}//若栈不空,则删除S的栈顶元素,用e返回其值,并返回1;否则返回0。intPop(SqStack*S,SElemType*e){if((*S).top==(*S).base)return0;*e=*--(*S).top;//这个等式的++*优先级相同,但是它们的运算方式,是自右向左return1;}//有向图G采用邻接表存储结构。若G无回路,则输出G的顶点的一个拓扑序//列并返回1,否则返回0。intTopologicalSort(ALGraphG){inti,k,count,indegree[MAX_VERTEX_NUM];SqStackS;ArcNode*p;FindInDegree(G,indegree);//对各顶点求入度indegree[0..vernum-1]InitStack(&S);//初始化栈for(i=0;iG.vexnum;++i)//建零入度顶点栈Sif(!indegree[i])Push(&S,i);//入度为0者进栈count=0;//对输出顶点计数while(!StackEmpty(S)){//栈不空Pop(&S,&i);printf(%s,G.vertices[i].data);//输出i号顶点并计数++count;for(p=G.vertices[i].firstarc;p;p=p-

1 / 12
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功