您的当前位置:首页正文

图的深度优先搜索遍历算法分析及其应用

来源:好兔宠物网
维普资讯 http://www.cqvip.com 2007正 青海师范大学学报(自然科学版) Journal of Qinghai Normal University(Natural Science) 2O07 No.3 第3期 图的深度优先搜索遍历算法分析及其应用 5r4 萍 ,冯桂莲2 (1.青海民族学院计算机系,青海西宁810007;2.青海民族学院电子工程与信息科学系,青海西宁810007) 摘要:本文通过具体的示例,详细分析以邻接表为存储结构进行图的深度优先搜索遍历的算法和在vc++环境中实现的完 整程序,最后介绍了基于该算法一些应用. 关键词:图;深度优先搜索;遍历;算法 中图分类号:TP311.12 文献标识码:A 文章编号:1001—7542{2OY/}03—0041—04 图(craph)是一种较线性表和树更为复杂的数据结构.图形结构中,结点之间的关系可以是任意的, 图中任意两个数据元素之间都可能相关.因此,在研究有关图的问题时,要考虑图中每个顶点的信息,访 问图中的各顶点,而访问图中各顶点的操作过程就是图的遍历.图的遍历算法是求解图的连通性问题、 拓扑排序和求关键路径等算法的基础. 1图的二元组定义 图C由集合V和E组成,记为:G=(V,E).其中:V是顶点的集合,E是V中顶点偶对的有穷集.通 常,将图c的顶点集和边集记为V(G)和E(G).E(c)可以是空集,若E(c)为空,则图G只有顶点而没有 边. 2图的存储结构 图的存储结构有邻接表、十字链表和多重邻接表等,本文主要介绍邻接表的存储结构.邻接表(Ad. jacency List)是图的一种链式存储结构.邻接表包含了一个顶点顺序表和每个顶点对应的单链表.顶点顺 序表中的顶点与图中的顶点一一对应,每个顶点的单链表中包含了邻接点域,链域和数据域.它是一个 动态结构,相当于是建立多个线性链表的操作u J. 为了便于理解,本文以无向图G作为具体示例(如图1所示),给 出以邻接表进行存储的图的数据结构. 现将图G的各顶点进行编号,其对应关系如表1所示: 表1顶点与编号的对应关系 2.1邻接表的数据结构定义 图1无向图G 将图c采用邻接表存储,其结构定义如下: #include<stdio.h> #include malloc.h“ #define MAX VE rEX NUM 30 #define n 8 #define e 9 #define TRUE 1 收稿日期:2OO7—03—16 作者简介:刘萍(1968一),女(汉族),青海同仁人,青海民族学院副教授 维普资讯 http://www.cqvip.com

42 #define- E 0 青海师范大学学报(自然科学版) edgenede*firstedge; 2007年 Booleam visited[MAX—VERTEX—NUMJ; typedef struct edgenede }vex.nde,eAdjHst[MAX—VERTEXNUM]; —typedef struct {hat adjvex;edgenede*nextedge;}edgenede; typedef struct vexnede {vexnode vertices; int vexnum,edgenum; {char data; 2.2构造算法 }AI ̄mph; 根据上述结构,我们可以构造出建立图G的邻接表的具体算法. void creatgraph(ALGraph&G) { i,j,k;edgenede*s; //图的邻接表 prinff(”以编号为顺序输入顶点信息(每个顶点占两位):”); f0lr(i=O;i<n;i++) {scaIlf(”%2d,,,&adjlist[i].atda); Adjlist[i].ifrstedge= E;} prm ̄(,输入组成边的点对(如:边为(1,2),则输入1 2/\Il,,); for(k=l;k<=e;k++) {prinff( ,第%d条边的点对:”,k);scarf(”%d%d,,,蕊, ); S=(edgenede*)mailoc(sizeof(edgenede));S一>adjvex=j; s一>nextedge=Adjlist[i].ifrstedge;Adjlist[i].ifrstedge=s; s=(edgenede*)malloc(sizeof(edgenede));S一>adjvex=i; s一>nextedge=Adjlist[j].ifrstedge;Adjlist[j].ifrstedge=s;}} 根据图的结构建立其所对应的邻接表后,可以用下述算法打印出邻接表. void show(ALGmph&G) {int i;edgenede*s; or(i=O;i<n;i++)f {s=AdjList[i].fisrtedge; {prinff(”%9d:一”,AdjList[i].data); if(Adjlist[i].ifrstedge!:FALSE) while(s!=FALSE) {prntif(”%5 ”,S一>adjvex); s=s一>nextedge;}} prnitf( \Il,,);}} 一显然,在建立邻接表的过程中,对邻接点的访问是无次序的,所以同 Vl 个图的邻接表表示不唯一.如图2所示是图G以顶点编号为0,1,2,1 V2 V3 2 V4 3 4 V5 3,4,5,6,7的输入顺序建立的邻接表. 3图的DFS遍历 5 V6 V7 图的遍历是从图中某个顶点出发,沿着某条搜索路径对图中其它顶6 V8 点访问且仅被访问一次.通常有两条遍历图的路径:深度优先搜索7 (Depth First Search)和广度优先搜索(Breadth Fisrt Search).它们对无向图 和有向图均适用. 3.1 DFS遍历的基本思想 图2图G的邻接表 假设初始状态是图中所有顶点未曾被访问,从图中某个顶点Vi出发,访问此顶点,然后依次从Vi 的未被访问的邻接点出发深度优先遍历图,直至图中所有和Vi有路径的顶点都被访问到为止;若此时 维普资讯 http://www.cqvip.com 第3期 刘萍,冯桂莲:图的深度优先搜索遍历算法分析及其应用 43 图中尚有顶点未被访问,则另选图中未曾访问的顶点为起始点,重复上述过程,直至图中所有顶点都被 访问为止 2. 3.2 DFS遍历的具体步骤 (1)先将图中所有顶点标记为“未被访问”标志; (2)输出起始顶点,同时置起始顶点“已访问”标记; (3)将起始顶点进栈; (4)当栈不为空时重复执行以下步骤: ①取当前栈顶顶点; ②若栈顶顶点存在未被访问的邻接顶点,则选择一个顶点并输出; ③置该顶点为“已访问”标志,将该顶点进栈;否则,当前顶点退栈. 3.3 DFS遍历的算法设计 结合示例,我们可以设一个辅助数组visited[n],将其初始值均置为“0”,一旦访问了顶点vi,便将 ivsitd[ie]置为“1”,其具体算法如下: voiddfstraverse(ALGmph&G) ,edgenede*・p; {int i;for(i=O;i<n;i++)visited[i]=FALSE; for(i=0;i<n;i++)printf(”%d一>”,AdjListEi].data); ivsitedEi]=TRUE; P=AdjList[i].firstedge; if(!visited[i]) while(p!:FALSE) dfs(G,i);} void dfs(ALGraph&G,int i){static int ivsitdlMAX—VERTEX—NUM];e{if(!visitd[ep一>adjvex]) dfs(G,P一>adjvex); P=P一>nextedge;}} 从上面算法看出,进行图的遍历时,对图中的每个顶点至多调用一次 ,因此,图的遍历过程实际 上是对每个顶点查找其邻接点的过程.此外,由于图的邻接表是不唯一的,所以由不同的邻接表得到的 图的遍历结果也是不相同的. 4主程序 在给出了数据结构类型和具体操作的算法之 后,可以编辑出以下主程序: void main() {int x;ALGraph G;creatgraph(G); p血tf( 输出如下邻接表:\n”);show(G); printf( \n输入访问出发点的顶点编号:”); s ̄anf(”%d,,, ); printf(”该图的深度优先搜索遍历序列为:\n\ t,,).dfs(G,x); prinff(”\b\b,,);} 5运行结果 该程序已经在Visual C++环境中调试通过,运 行时输入的具体数据和相应结果如图3所示: 图3程序运行结果 维普资讯 http://www.cqvip.com 青海师范大学学报(自然科学版) 2O07年 6 dfs遍历序列结果讨论 (1)只给定一个无向图,则dfs遍历序列不一定唯一.从图的某顶点vi出发进行搜索时,若vi的邻 接点有多个尚未访问,可任选一个访问. (2)只有确定了图的邻接表的内容及起始顶点, 遍历序列才能唯一.因为邻接表里的邻接点域的 内容与建表时的输人次序相关. 7基于dfs算法的应用 (1)求无向图中连通分量的个数 求解该问题只要在算法dfstraverse中加人一个计数器count,每调用一次 后,使count加1,最后 count的值就是无向图中连通分量的个数. (2)求解无向图中通过给定顶点Vi的简单回路的算法[3】 从给定的顶点Vi出发进行深度优先搜索,搜索过程中每访问一个顶点,判别它是否为vi,若是,则 说明已找到一条回路;杏则继续搜索.因此,用一个顺序栈记录构成回路的顶点序列,把访问顶点的操作 改为顶点的人栈,此时若从某一顶点出发搜索完再回溯,则做退栈操作.另外再设置一个标志found,其 初值为FALSE,当找到回路后改为TRUE. 综上所述,图的结构比较复杂,在编写图的DFS算法和程序时,关键要掌握它的遍历思想,并且能 使用一些编程技巧和经验对程序进行优化.在完全理解DFS算法的基础上,再去解决有关图的一些问 题就显得容易了. 参考文献: [1】严蔚敏,吴伟民.数据结构[M】.北京:清华大学出版社.1997:160-178. [2】胡学钢.数据结构算法设计指导[M】.北京:清华大学出版社.1999:198-216. [3】于晓敏,唐丽.用遍历方式求解图中是否存在回路问题[J].齐齐哈尔大学学报,2OO4,2: ̄46. Analysis and Application For Depth—first Search Algorithm Of Graph LIU胁 ,FENG Gui-lian (1.Department OfComputer,Qinghai Nationalities University,Xining 810007,China; 2.Department of Electronic Engineering and Information Science。Qinghai Nationaliites University,yani ̄810007,China) Abstract:This paper analyzes carefully the Depth—first Search Algorithm ofthe Graph that regarded the adja— eeney list as storage struc ̄re through particular examples,and also analyzes the whole program realized in ve++. At last.it produces 8咖e application based Oil this asorithm. Key words:graph;depth——first search;traversing;algorithm 

因篇幅问题不能全部显示,请点此查看更多更全内容