实现有向图强连通分量的算法数据结构课程设计报告.docx
- 文档编号:2444002
- 上传时间:2022-10-29
- 格式:DOCX
- 页数:14
- 大小:55.97KB
实现有向图强连通分量的算法数据结构课程设计报告.docx
《实现有向图强连通分量的算法数据结构课程设计报告.docx》由会员分享,可在线阅读,更多相关《实现有向图强连通分量的算法数据结构课程设计报告.docx(14页珍藏版)》请在冰豆网上搜索。
实现有向图强连通分量的算法数据结构课程设计报告
课程设计报告
课程设计名称:
数据结构课程设计
课程设计题目:
实现求有向图强连通分量的算法
院(系):
专业:
班级:
学号:
姓名:
指导教师:
1系统分析
1.1题目介绍
在键盘上输入有向图,对任意给定的图(顶点数和边数自定),建立它的邻接表并输出。
然后判断该图是否强连通。
如果是强连通图,求出该图的所有强连通分量并输出字符。
1.2功能要求
首先输入图的类型,有向图(因为遍历与权值无关,所以没有涉及带权图)。
然后输入图的顶点数、边数和各条边,之后生成该图的邻接表并输出。
再输入要遍历该图的起点,然后从所输入的点深度搜索该图的十字链表,并按遍历顺序输出顶点内容。
之后决定是否继续遍历该图或输入另一个需要遍历的图亦或是结束程序。
要求采取简单方便的输入方式。
并且系统要求提供观察有向图图形结构和各强连通分量结构的功能。
2概要设计
2.1流程图
根据程序要求,设计流程图如下:
是
否
图2.1——流程图
2.2结构体说明
//有向图十字链表存储表示
typedefstructarcbox
inttailvex,headvex;//该弧的尾和头顶点的位置
structarcbox*hlink,*tlink;//分别为弧头相同和弧尾相同的弧的链域
infotype*info;//该弧相关信息的指针
}arcbox;
typedefstructvexnode
{
vextypedata;
arcbox*firstin,*firstout;//分别指向该顶点第一条入弧和出弧
}vexnode;
typedefstruct
{
vexnodexlist[max_vex_num];//表头向量
intvexnum,arcnum;//有向图的当前顶点数和弧数
}OLgraph;
3详细设计
3.1遍历函数设计
3.1.1Kosaraju算法基本思路:
这个算法可以说是最容易理解,最通用的算法,其比较关键的部分是同时应用了原图G和反图GT。
(步骤1)先用对原图G进行深搜形成森林(树),(步骤2)然后任选一棵树对其进行深搜(注意这次深搜节点A能往子节点B走的要求是EAB存在于反图GT),能遍历到的顶点就是一个强连通分量。
余下部分和原来的森林一起组成一个新的森林,继续步骤2直到没有顶点为止。
改进思路:
当然,基本思路实现起来是比较麻烦的(因为步骤2每次对一棵树进行深搜时,可能深搜到其他树上去,这是不允许的,强连通分量只能存在单棵树中),我们当然不这么做,我们可以巧妙的选择第二深搜选择的树的顺序,使其不可能深搜到其他树上去。
想象一下,如果步骤2是从森林里选择树,那么哪个树是不连通(对于GT来说)到其他树上的呢?
就是最后遍历出来的树,它的根节点在步骤1的遍历中离开时间最晚,而且可知它也是该树中离开时间最晚的那个节点。
这给我们提供了很好的选择,在第一次深搜遍历时,记录时间i离开的顶点j,即numb[i]=j。
那么,每次只需找到没有找过的顶点中具有最晚离开时间的顶点直接深搜(对于GT来说)就可以了。
每次深搜都得到一个强连通分量。
隐藏性质:
分析到这里,已经知道怎么求强连通分量了。
但是,如果把求出来的每个强连通分量收缩成一个点,并且用求出每个强连通分量的顺序来标记收缩后的节点,那么这个顺序其实就是强连通分量收缩成点后形成的有向无环图的拓扑序列。
首先,应该明确搜索后的图一定是有向无环图,如果还有环,那么环上的顶点对应的所有原来图上的顶点构成一个强连通分量,而不是构成环上那么多点对应的独自的强连通分量了。
然后就是为什么是拓扑序列,我们在改进分析的时候,不是先选的树不会连通到其他树上(对于反图GT来说),也就是后选的树没有连通到先选的树,也即先出现的强连通分量收缩的点只能指向后出现的强连通分量收缩的点。
那么拓扑序列不是理所当然的吗?
这就是Kosaraju算法的一个隐藏性质。
3.1.2伪代码
Kosaraju_Algorithm:
step1:
对原图G进行深度优先遍历,记录每个节点的离开时间。
step2:
选择具有最晚离开时间的顶点,对反图GT进行遍历,删除能够遍历到的顶点,这些顶点构成一个强连通分量。
step3:
如果还有顶点没有删除,继续step2,否则算法结束。
3.1.3.实现代码:
#include
usingnamespacestd;
constintMAXN=110;
typedefintAdjTable[MAXN];//邻接表类型
intn;
boolflag[MAXN];//访问标志数组
intbelg[MAXN];//存储强连通分量,其中belg[i]表示顶点i属于第belg[i]个强连通分量
intnumb[MAXN];//结束时间标记,其中numb[i]表示离开时间为i的顶点
AdjTableadj[MAXN],radj[MAXN];//邻接表,逆邻接表
//用于第一次深搜,求得numb[1..n]的值
voidVisitOne(intcur,int&sig)
{
flag[cur]=true;
for(inti=1;i<=adj[cur][0];++i)
{
if(false==flag[adj[cur][i]])
{
VisitOne(adj[cur][i],sig);
}
}
numb[++sig]=cur;
}
//用于第二次深搜,求得belg[1..n]的值
voidVisitTwo(intcur,intsig)
{
flag[cur]=true;
belg[cur]=sig;
for(inti=1;i<=radj[cur][0];++i)
{
if(false==flag[radj[cur][i]])
{
VisitTwo(radj[cur][i],sig);
}
}
}
//Kosaraju算法,返回为强连通分量个数
intKosaraju_StronglyConnectedComponent()
{
inti,sig;
//第一次深搜
memset(flag+1,0,sizeof(bool)*n);
for(sig=0,i=1;i<=n;++i)
{
if(false==flag[i])
{
VisitOne(i,sig);
}
}
//第二次深搜
memset(flag+1,0,sizeof(bool)*n);
for(sig=0,i=n;i>0;--i)
{
if(false==flag[numb[i]])
{
VisitTwo(numb[i],++sig);
}
}
returnsig;
}
3.2调试分析和测试结果
编译、运行及调试环境:
MicrosoftVisualC++
3.2.1调试分析
一.在输入图信息的时候,若输入非法字符,程序会异常终止。
例如程序要求输入一个整型,用户却输入了一个字母,这时候会出现异常。
只是程序是否健壮性的一个体现。
先用字符串接收字符,转换成整型后再判断是否符合要求。
如果不符合便提示用户按要求重新输入。
还有其他一些类似的输入异常,都是采用类似的处理方法。
二.作为一个完整的程序,友好的界面是必须的。
因次程序中适当地采用人性化的提示命令,使得界面更加简洁,明了。
3.2.2测试结果
测试案例:
图3.2.2——案例结构图
图1——程序运行
图2——程序结果
参考文献
[1]王为青,张圣亮.C语言实战105例.人民邮电出版社,2007.3
[2]严蔚敏,吴伟民.数据结构(C语言版).清华大学出版社,1997.4
[3]袁平波.数据结构实验指导,合肥.中国科学技术大学出版社,2010.7
[4]杨克昌,刘志辉.趣味C程序设计集锦,北京.中国水利水电出版社,2010.1
附录(关键部分程序清单)
#include
#include
typedefintvextype;
typedefintinfotype;
typedefintstatus;
#definemax_vex_num15
#defineFALSE0
#defineTRUE1
#defineOVERFLOW-2
//有向图十字链表存储表示
typedefstructarcbox
{
inttailvex,headvex;
structarcbox*hlink,*tlink;
infotype*info;
}arcbox;
typedefstructvexnode
{
vextypedata;
arcbox*firstin,*firstout;
}vexnode;
typedefstruct
{
vexnodexlist[max_vex_num];
intvexnum,arcnum;
}OLgraph;
intLocatevex(OLgraphG,intd)
{
intk;
for(k=0;k { if(G.xlist[k].data==d) returnk; } } statuscreat_DG(OLgraph&G) { inta,k,incinfo,i,j; vextypetailnum,headnum; arcbox*p; printf("输入结点个数: "); scanf("%d",&G.vexnum); printf("输入弧的条数: "); scanf("%d",&G.arcnum); printf("输入有无权值判定符(0表示没有,1表示有): "); scanf("%d",&incinfo); printf("输入所有弧结点数据: "); for(a=0;a { scanf("%d",&G.xlist[a].data); G.xlist[a].firstin=NULL; G.xlist[a].firstout=NULL; } for(k=0;k { printf("输入弧头结点和弧尾结点的数据: "); scanf("%d,%d",&tailnum,&headnum); i=Locatevex(G,tailnum); j=Locatevex(G,headnum); p=(arcbox*)malloc(sizeof(arcbox)); p->tailvex=i; p->headvex=j; p->hlink=G.xlist[j].firstin; p->tlink=G.xlist[i].firstout; //p->info=NULL; G.xlist[j].firstin=G.xlist[i].firstout=p; if(incinfo) { printf("输入权值: "); scanf("%d",p->info); } }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实现 连通 分量 算法 数据结构 课程设计 报告