图的遍历深度优先遍历和广度优先遍历(2)幻灯片.ppt
《图的遍历深度优先遍历和广度优先遍历(2)幻灯片.ppt》由会员分享,可在线阅读,更多相关《图的遍历深度优先遍历和广度优先遍历(2)幻灯片.ppt(44页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、图的遍历深度优先遍历和广度优先遍历第1页,共44页,编辑于2022年,星期五20、图的遍历深度优先遍历和广度优、图的遍历深度优先遍历和广度优先遍历先遍历掌握图的深度优先和广度优先遍历的性掌握图的深度优先和广度优先遍历的性质和方法,以及基于邻接矩阵和邻接表质和方法,以及基于邻接矩阵和邻接表存储结构的递归和非递归的算法实现存储结构的递归和非递归的算法实现第2页,共44页,编辑于2022年,星期五目目录录20.1概述概述20.2深度优先遍历深度优先遍历20.3深度优先遍历的性质深度优先遍历的性质20.4广度优先遍历广度优先遍历20.5广度优先遍历的性质广度优先遍历的性质第3页,共44页,编辑于202
2、2年,星期五2020、图的遍历图的遍历 从从这这节节起起,我我们们介介绍绍图图的的一一些些重重要要操操作作的的实实现现,包包括括遍遍历历、拓拓扑扑排排序序、关关键键路路径径等等。另另有有一一些些重重要要操操作作,如如最最短短路路径径问问题题、最最小小生生成成树树问问题题,由由于于主主要要难难点点在在于于算算法法,所所以以我我们们安安排排在在后后面面的的算算法法设设计计章章节中介绍。节中介绍。图图的的遍遍历历与与树树的的遍遍历历一一样样具具有有十十分分重重要要的的作作用用,图图的的许多其他操作(算法)都与遍历相关。许多其他操作(算法)都与遍历相关。第4页,共44页,编辑于2022年,星期五20.
3、1 20.1 概述概述 图的遍历的含意是,图的遍历的含意是,从图中某结点出发,按某既定方式访问图中从图中某结点出发,按某既定方式访问图中各个可访问到的结点,使每个可访问到的结点恰被访问一次。各个可访问到的结点,使每个可访问到的结点恰被访问一次。图的遍历方式有两种:深度优先与广度优先方式,分别对应于树的图的遍历方式有两种:深度优先与广度优先方式,分别对应于树的先根遍历与层序遍历。先根遍历与层序遍历。树中不存在回路,但图中可能有回路。因此,当沿回路进树中不存在回路,但图中可能有回路。因此,当沿回路进行扫描时,一个结点可能被扫描到多次,可能导致死循环。为行扫描时,一个结点可能被扫描到多次,可能导致死
4、循环。为了避免这种情形,在遍历中,应为每个结点设立一个访问标志,了避免这种情形,在遍历中,应为每个结点设立一个访问标志,每扫描到一个结点,要检查它的访问标志,若标志为每扫描到一个结点,要检查它的访问标志,若标志为“未访问未访问”,则按正常方式对其进行处理(如访问或转到它的邻接点等),则按正常方式对其进行处理(如访问或转到它的邻接点等),否则放过它,扫描下一个结点。,否则放过它,扫描下一个结点。第5页,共44页,编辑于2022年,星期五 访问标志的设置有两种方法:访问标志的设置有两种方法:在描述图结的记录中增设一个访问标志位。这在描述图结的记录中增设一个访问标志位。这种方法的优点是,访问种方法的
5、优点是,访问“访问标志访问标志”的方法与访问的方法与访问结点的方法一致。如果访问标志需要与图结构同生结点的方法一致。如果访问标志需要与图结构同生命期,则这种方法比较合适。但是,若访问标志要命期,则这种方法比较合适。但是,若访问标志要重复使用,就必须先重新初始化访问标志。如果图重复使用,就必须先重新初始化访问标志。如果图结点的存储不利于顺序访问,这往往也是个遍历问结点的存储不利于顺序访问,这往往也是个遍历问题!题!另设一个另设一个“访问数组访问数组”,令它的每个元素对应于一个,令它的每个元素对应于一个图结点访问标志。这种方法的访问标志很容易多次初始化图结点访问标志。这种方法的访问标志很容易多次初
6、始化。第6页,共44页,编辑于2022年,星期五从图中某一结点出发,一趟只能遍历到它所在的极大从图中某一结点出发,一趟只能遍历到它所在的极大连通分量中的结点,要想遍历到图中各结点,需进行连通分量中的结点,要想遍历到图中各结点,需进行多趟遍历(每趟遍历一个极大连通分量)。该过程可多趟遍历(每趟遍历一个极大连通分量)。该过程可描述为:描述为:for(图中每个结点图中每个结点v)if(v尚未被访问过尚未被访问过)从从v出发遍历该图出发遍历该图;下面只考虑从一点出发遍历,因此有可能会出现下面只考虑从一点出发遍历,因此有可能会出现遍历不到的点。即那些初始点无路径可达的点,遍历不到的点。即那些初始点无路径
7、可达的点,是遍历不到的。是遍历不到的。第7页,共44页,编辑于2022年,星期五20.2 20.2 深度优先遍历深度优先遍历(一一)遍历规则遍历规则从图中某结点从图中某结点v0出发,出发,深度优先遍历(深度优先遍历(DFS:DepthFirstSearch)图的规则为:图的规则为:访问访问v0;对对v0的各个出点的各个出点v01,v02,v0m,每次从它们中,每次从它们中按一定方式(也可任选)选取一个未被访问过的结点,按一定方式(也可任选)选取一个未被访问过的结点,从该结点出发按深度优先遍历方式遍历。从该结点出发按深度优先遍历方式遍历。显然,因为我们没有规定对出点的遍历次序,所以,图显然,因为
8、我们没有规定对出点的遍历次序,所以,图的深度优先遍历结果一般不唯一的深度优先遍历结果一般不唯一。第8页,共44页,编辑于2022年,星期五 例例如如,对对图图20 1给给出出的的有有向向图图与与无无向向图图,一一些些遍遍历历结结果果(结点访问次序)为:(结点访问次序)为:左图:从左图:从1出发:出发:1,2,4,5;或;或1,5,2,4从从2出发:出发:2,1,5,4;或;或2,4,1,5右图:从右图:从a出发:出发:a,b,c,d;或;或a,b,d,c;12543 3abcd图图20 1一个有向图(左)和无向图一个有向图(左)和无向图第9页,共44页,编辑于2022年,星期五1.一般算法 下
9、面考虑深度优先遍历的递归实现的一般方法(存储结构无下面考虑深度优先遍历的递归实现的一般方法(存储结构无关)。关)。图的深度优先遍历与二叉树的前序遍历相似。不同之处有:图的深度优先遍历与二叉树的前序遍历相似。不同之处有:二叉树每个结点至多有两个可达邻接点(左右儿子),二叉树每个结点至多有两个可达邻接点(左右儿子),而图的可达邻接点数目不定;而图的可达邻接点数目不定;对二叉树,沿可达邻接点搜索时不会发生回绕,但对图,若对二叉树,沿可达邻接点搜索时不会发生回绕,但对图,若不加特别控制,就有可能回绕。不加特别控制,就有可能回绕。下面是图的深度优先遍历递归算法的一般性描述。如果要另下面是图的深度优先遍历
10、递归算法的一般性描述。如果要另设一个数组作为访问标志,则该数组要在递归过程(函数)设一个数组作为访问标志,则该数组要在递归过程(函数)之外初始化为之外初始化为“未访问未访问”。(二)递归实现方法(二)递归实现方法第10页,共44页,编辑于2022年,星期五longDFS(图图g,结点,结点v0)/图深度优先遍历递归算法。从结点图深度优先遍历递归算法。从结点v0出发,深度优先遍历出发,深度优先遍历图图g,返回访问到的结点总数,返回访问到的结点总数intnNodes;/寄存访问到的结点数目寄存访问到的结点数目访问访问v0;为为v0置已访问标志置已访问标志;nNodes=1;求出求出v0的第的第1个
11、可达邻接点个可达邻接点v;while(v存在存在)if(v未被访问过未被访问过)nNodes=nNodes+DFS(g,v);求出求出v0的下个可达邻接点的下个可达邻接点v;returnnNodes;第11页,共44页,编辑于2022年,星期五12543 3 1 2 3 4 5 1 2 3 4 5 1 0 1 0 0 1 1 0 1 0 0 1 2 1 0 0 1 0 2 1 0 0 1 0 3 0 0 0 0 1 3 0 0 0 0 1 4 1 0 0 0 0 4 1 0 0 0 0 5 0 0 0 0 0 5 0 0 0 0 0所示图的邻接矩阵所示图的邻接矩阵所示图的邻接矩阵所示图的邻接矩
12、阵g g1121304151图图图图 2020 1 1有向图访问标识数组访问标识数组visited1245输出数组输出数组resu例如从例如从1点深度优先遍历,先把点深度优先遍历,先把1设置访问标志,并置入输出数组设置访问标志,并置入输出数组resu,然后从邻接矩阵的第一行,然后从邻接矩阵的第一行,扫描各列,找到最近的邻接点扫描各列,找到最近的邻接点2,将其设置访问标志,并进入输出数组,接着从邻接矩阵,将其设置访问标志,并进入输出数组,接着从邻接矩阵的的2行扫描,找到第一个构成边的点是行扫描,找到第一个构成边的点是1,检查访问标识数组,发现,检查访问标识数组,发现1已经访问过,跳过,找第二个构
13、已经访问过,跳过,找第二个构成边成边的点的点4,设置访问标识,进入输出数组,再从邻接矩阵的第,设置访问标识,进入输出数组,再从邻接矩阵的第4行扫描,寻找构成边的点,行扫描,寻找构成边的点,除除1外在无其他点,返回外在无其他点,返回2行,继续寻找,也无新点,返回行,继续寻找,也无新点,返回1,找到,找到5,将,将5置访问标志,进入输出数组,置访问标志,进入输出数组,1行再无其他新点,遍历结束,返回遍历元素个数为行再无其他新点,遍历结束,返回遍历元素个数为4。第12页,共44页,编辑于2022年,星期五 2 2邻接矩阵实现邻接矩阵实现 这里我们为了突出主题、简化问题,假定图是用一般的邻接矩阵存储,
14、这里我们为了突出主题、简化问题,假定图是用一般的邻接矩阵存储,邻接矩阵用简单的二维数组表示(静态),用邻接矩阵用简单的二维数组表示(静态),用0和和1分别表示无边和有边。分别表示无边和有边。图结点用自然数编号。图结点用自然数编号。longDFS1(intgCNST_NumNodes,longn,longv0,char*visited,long*resu,long&top)/深度优先遍历图(递归)。图深度优先遍历图(递归)。图g为邻接矩阵,结点编号为为邻接矩阵,结点编号为 0n.返回实际遍历到的结点数目返回实际遍历到的结点数目/visited是访问标志数组,调用本函数前,应为其分配空间并初是访问
15、标志数组,调用本函数前,应为其分配空间并初始化为全始化为全0(未访问未访问)/resu为一维数组,用于存放所遍历到的结点的编号,调用本函为一维数组,用于存放所遍历到的结点的编号,调用本函数前,应为其分配空间数前,应为其分配空间第13页,共44页,编辑于2022年,星期五longnNodes,i;nNodes=1;resutop+=v0;/将访问到的结点依次存于将访问到的结点依次存于resuvisitedv0=1;/为为v0置已访问标志置已访问标志for(i=0;in;i+)/依次从依次从v0的各个出点出发,深度优先遍历图的各个出点出发,深度优先遍历图if(gv0i!=0)/若若是边是边if(!
16、visitedi)/若结点若结点i未被访问过未被访问过nNodes=nNodes+DFS1(g,n,i,visited,resu);/从从i起深度优先遍历图起深度优先遍历图returnnNodes;第14页,共44页,编辑于2022年,星期五 AA如如果果不不想想让让visited或或top做做为为函函数数参参数数,也也可可以以在在函函数数中中将将其其定定义义为为static型型量量。但但是是,这这样样的的程程序序是是不不可可再再入入的的,即即函函数数再再次次被被调调用用时时,static型型的的量量也也不不重重新新初始化,造成错误!初始化,造成错误!上面函数中的参数上面函数中的参数visit
17、ed和和top实质上是中间变量,只是为了避免在实质上是中间变量,只是为了避免在递归调用时重新初始化而放在参数表中,造成使用的不方便,为此,做递归调用时重新初始化而放在参数表中,造成使用的不方便,为此,做个包装程序:个包装程序:longDFS1(intgCNST_NumNodes,longn,longv0,long*resu)char*visited;longtop=0;visited=newcharn;for(longi=0;in;i+)visitedi=0;longnum=DFS1(g,n,v0,visited,resu,top);deletevisited;returnnum;第15页,共
18、44页,编辑于2022年,星期五12543 312452b51d451a1c2e3f45对应的邻接表对应的邻接表图图20 2有向图1121304151访问标识数组访问标识数组visited输出数组输出数组resu地址起 终权信息链a1 2bb1 5c2 1dd2 4e3 5f4 1邻接表边PNodes终点终点2作为下次的始点,由作为下次的始点,由于于1点已访问过,跳过,找点已访问过,跳过,找到到4,记标识,送输出,记标识,送输出,4有有作为新的始点重复上述过程作为新的始点重复上述过程第16页,共44页,编辑于2022年,星期五 3邻接表深度优先遍历的实现深度优先遍历的实现 templatelo
19、ngDFS2(TGraphNodeAL*nodes,longn,longv0,char*visited,long*resu,long&top)/深度优先遍历用邻接表表示的图。深度优先遍历用邻接表表示的图。nodes是邻接表的头数组,是邻接表的头数组,n为结点个数为结点个数(编号为(编号为0n)。)。/v0为遍历的起点。返回实际遍历到的结点的数目。为遍历的起点。返回实际遍历到的结点的数目。/visited是访问标志数组,调用本函数前,应为其分配空间并初始化为是访问标志数组,调用本函数前,应为其分配空间并初始化为全全0(未访问未访问)/resu为一维数组,用于存放所遍历到的结点的编号,调用本函数前
20、,应为一维数组,用于存放所遍历到的结点的编号,调用本函数前,应为其分配空间为其分配空间longnNodes,i;TGraphEdgeAL*p;nNodes=1;第17页,共44页,编辑于2022年,星期五resutop+=v0;/将访问到的结点依次存于将访问到的结点依次存于resuvisitedv0=1;/置置v0为为“已访问已访问”标志标志p=nodesv0.firstOutEdge;/求出求出v0的第一个出点的第一个出点pwhile(p!=NULL)if(!visitedp-endNo)/若若p未访问,则从未访问,则从p出发深度优先遍历出发深度优先遍历nNodes=nNodes+DFS2(
21、nodes,n,p-endNo,visited,resu,top);p=p-next;/令令p指向指向v0的下个出点的下个出点returnnNodes;与邻接矩阵的情况类似,也可以对该程序与邻接矩阵的情况类似,也可以对该程序“包装包装”,以隐蔽,以隐蔽visited和和top。第18页,共44页,编辑于2022年,星期五(三三)非递归实现方法非递归实现方法1一般方法一般方法下下面面考考虑虑深深度度优优先先遍遍历历的的非非递递归归实实现现的的一一般般方方法法(存存储储结结构构无无关)。关)。图图的的深深度度优优先先遍遍历历的的非非递递归归实实现现,仍仍然然与与二二叉叉树树的的前前序序遍遍历历非非
22、递递归归实实现现相相似似。不不同同之之处处有有:二二叉叉树树每每个个结结点点至至多多有有两两个个可可达达邻邻接接点点(左左右右儿儿子子),而而图图的的可可达达邻邻接接点点数数目目不不定定,因因此此,当当结结点点重重新新出出现现在在栈栈顶顶时时,不不能能一一定定出出栈栈,而而是是要要根根据据它它的的各各出出点点是是否否都都已已被被访访问问过过来来决决定定(是是则则出出栈栈);对对二二叉叉树树,沿沿可可达达邻邻接接点点搜搜索索时时不不会会发发生生回回绕绕,但但对对图图,若若不不加特别控制,就有可能回绕。加特别控制,就有可能回绕。第19页,共44页,编辑于2022年,星期五longDFS_NR(图图
23、g,结点,结点v0)/图深度优先遍历非递归算法。从结点图深度优先遍历非递归算法。从结点v0出发,深度优先遍历出发,深度优先遍历图图g,返回访问到的结点总数,返回访问到的结点总数intnNodes;/寄存访问到的结点数目寄存访问到的结点数目访问访问v0;为为v0置已访问标志置已访问标志;v0进栈进栈S;nNodes=1;求出求出v0的第的第1个可达邻接点个可达邻接点v;深度优先遍历非递归算法的一般性描述。深度优先遍历非递归算法的一般性描述。第20页,共44页,编辑于2022年,星期五while(栈栈S不空不空)v=栈栈S顶部元素;顶部元素;求求v的下个未访问过的出点的下个未访问过的出点i;访问访
24、问i;为为i置已访问标志置已访问标志;i进栈进栈S;nNodes+;if(v已无未被访问过的出点已无未被访问过的出点)出栈;出栈;returnnNodes;上面的伪码描述与具体的数据结构无关。下面的程序分别给出上面的伪码描述与具体的数据结构无关。下面的程序分别给出了针对邻接矩阵与邻接表的算法模型。了针对邻接矩阵与邻接表的算法模型。第21页,共44页,编辑于2022年,星期五2邻接矩阵实现邻接矩阵实现longDFS1_NR(intgCNST_NumNodes,longn,longv0,long*resu)/深度优先遍历图深度优先遍历图(非递归)。图非递归)。图g为邻接矩阵,为邻接矩阵,结点编号为
25、结点编号为0n.返回实际遍历到的结点数目返回实际遍历到的结点数目/resu为一维数组,用于存放所遍历到的结点的为一维数组,用于存放所遍历到的结点的 编号,调用本函数前,应为其分配空间编号,调用本函数前,应为其分配空间longnNodes,i,v;longtop;char*visited;long*s;visited=newcharn;for(i=0;in;i+)visitedi=0;s=newlongn+1;top=0;nNodes=0;resunNodes+=v0;/将访问到的结点依次存于将访问到的结点依次存于resuvisitedv0=1;/为为v0置已访问标志置已访问标志第22页,共44
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 图的遍历深度优先遍历和广度优先遍历 2幻灯片 遍历 深度 优先 广度 幻灯片
限制150内