图的遍历和树的遍历类似。图的遍历是指从图中的某个顶点出发,对图中的所有顶点访问且仅访问一次的过程。通常有两种遍历次序方案:深度优先遍历和广度优先遍历。

  一、深度优先遍历

  深度优先遍历(Depth_First_Search),也称为深度优先搜索,简称为DFS。深度优先遍历类似于树的前序遍历。

  DFS算法描述:从图的某个顶点v开始访问,然后访问它的任意一个邻接点w1,;再从w1出发,访问与w1邻接但未被访问过的顶点w2;然后从w2出发,进行类似访问,如此进行下去,直至所有邻接点都被访问过为止。接着,退回一步,退回到前一次刚访问过的顶点,看是否还有其他未被访问过的邻接点。如果有,则访问此顶点,之后再从此顶点出发,进行与前述类似的访问。重复上述过程,直到连通图中所有顶点都被访问过为止。

  二、广度优先遍历

  广度优先遍历(Breadth_First_Search),又称为广度优先搜索,简称BFS。图的广度优先遍历类似于树的层序遍历。

  BFS算法描述:从图中的某个顶点v开始,先访问该顶点,再依次访问该顶点的每一个未被访问过的邻接点w1,w2,...;然后按此顺序访问顶点w1,w2...的各个还未 被访问过的邻接点。重复上述过程,直到图中的所有顶点都被访问过为止。

  以下面的例子为例,深度优先遍历的顶点访问序列为:{A B C D E F G H I};广度优先遍历的顶点访问序列为:{A B F C I G E D H}

  

  

  三、图的遍历算法实现

  1.深度优先遍历

  (1)C语言实现

/* 邻接矩阵的深度优先递归算法 */
void DFS(MGraph G, int i)
{
int j;
visited[i] = TRUE;
printf("%c ", G.vexs[i]);/* 打印顶点,也可以其它操作 */
for(j = ; j < G.numVertexes; j++)
if(G.arc[i][j] == && !visited[j])
DFS(G, j);/* 对为访问的邻接顶点递归调用 */
} /* 邻接矩阵的深度遍历操作 */
void DFSTraverse(MGraph G)
{
int i;
for(i = ; i < G.numVertexes; i++)
visited[i] = FALSE; /* 初始所有顶点状态都是未访问过状态 */
for(i = ; i < G.numVertexes; i++)
if(!visited[i]) /* 对未访问过的顶点调用DFS,若是连通图,只会执行一次 */
DFS(G, i);
}

  (2)Java语言实现

package bigjun.iplab.adjacencyMatrix;

public class Depth_First_Search {

    private static boolean[] visited;                // 访问标识数组

    public static void DFSTraverse(AdjacencyMatrixGraphINF G) throws Exception{
System.out.print("图的深度优先遍历序列为: ");
visited = new boolean[G.getVexNum()];
for (int v = 0; v < G.getVexNum(); v++) // 访问标志数组初始化都为false,即未访问过
visited[v] = false;
for (int v = 0; v < G.getVexNum(); v++) // 如果没有访问过就对顶点调用深度优先遍历算法
if (!visited[v])
DFS(G, v);
System.out.println();
} private static void DFS(AdjacencyMatrixGraphINF G, int v) throws Exception {
visited[v] = true; // 先将访问标识数组置为true
System.out.print(G.getVex(v).toString() + " ");
for (int w = G.firstAdjvex(v); w >= 0; w = G.nextAdjvex(v, w))
if (!visited[w])
DFS(G, w);
} }

  2.广度优先遍历

  (1)C语言实现

Boolean visited[MAXSIZE]; /* 访问标志的数组 */

/* 邻接表的深度优先递归算法 */
void DFS(GraphAdjList GL, int i)
{
EdgeNode *p;
visited[i] = TRUE;
printf("%c ",GL->adjList[i].data);/* 打印顶点,也可以其它操作 */
p = GL->adjList[i].firstedge;
while(p)
{
if(!visited[p->adjvex])
DFS(GL, p->adjvex);/* 对为访问的邻接顶点递归调用 */
p = p->next;
}
} /* 邻接表的深度遍历操作 */
void DFSTraverse(GraphAdjList GL)
{
int i;
for(i = ; i < GL->numVertexes; i++)
visited[i] = FALSE; /* 初始所有顶点状态都是未访问过状态 */
for(i = ; i < GL->numVertexes; i++)
if(!visited[i]) /* 对未访问过的顶点调用DFS,若是连通图,只会执行一次 */
DFS(GL, i);
}

  (2)Java语言实现

package bigjun.iplab.adjacencyMatrix;

import bigjun.iplab.linkQueue.LinkQueue;

public class Breadth_First_Search {

    private static boolean[] visited;

    public static void BFSTraverse(AdjacencyMatrixGraphINF G) throws Exception{
System.out.print("图的广度优先遍历序列为: ");
visited = new boolean[G.getVexNum()];
for (int v = 0; v < G.getVexNum(); v++) // 访问标志数组初始化都为false,即未访问过
visited[v] = false;
for (int v = 0; v < G.getVexNum(); v++) // 如果没有访问过就对顶点调用深度优先遍历算法
if (!visited[v])
BFS(G, v);
System.out.println();
} private static void BFS(AdjacencyMatrixGraphINF G, int v) throws Exception {
visited[v] = true; // 先将访问标识数组置为true
System.out.print(G.getVex(v).toString() + " "); // 然后访问对应数组下标的顶点
LinkQueue queue = new LinkQueue(); // 链队列初始化
queue.queueEnter(v); // 将访问过的顶点的数组下标入队列
while (!queue.isqueueEmpty()) {
int u = (Integer) queue.queuePoll(); // 队列队头元素出队列并赋值给u
for (int w = G.firstAdjvex(u); w >= 0; w = G.nextAdjvex(u, w)) {
if (!visited[w]) {
visited[w] = true;
System.out.print(G.getVex(w).toString() + " ");
queue.queueEnter(w);
}
}
}
} }

  四、(举例)邻接矩阵的深度优先遍历和广度优先遍历

    // 手动创建一个无向图
public static AdjacencyMatrixGraphINF createUDGByYourHand() {
Object vexs_UDG[] = {"A", "B", "C", "D", "E", "F", "G", "H", "I"};
int[][] arcs_UDG = new int[vexs_UDG.length][vexs_UDG.length];
for (int i = 0; i < vexs_UDG.length; i++) // 构造无向图邻接矩阵
for (int j = 0; j < vexs_UDG.length; j++)
arcs_UDG[i][j] = 0;
arcs_UDG[0][1] = 1;
arcs_UDG[0][5] = 1;
arcs_UDG[1][2] = 1;
arcs_UDG[1][6] = 1;
arcs_UDG[1][8] = 1;
arcs_UDG[2][3] = 1;
arcs_UDG[2][8] = 1;
arcs_UDG[3][4] = 1;
arcs_UDG[3][6] = 1;
arcs_UDG[3][7] = 1;
arcs_UDG[3][8] = 1;
arcs_UDG[4][5] = 1;
arcs_UDG[4][7] = 1;
arcs_UDG[5][6] = 1;
for (int i = 0; i < vexs_UDG.length; i++) // 构造无向图邻接矩阵
for (int j = i; j < vexs_UDG.length; j++)
arcs_UDG[j][i] = arcs_UDG[i][j];
return new AdjMatGraph(GraphKind.UDG, vexs_UDG.length, 14, vexs_UDG, arcs_UDG);
} public static void main(String[] args) throws Exception {
AdjMatGraph DNG_Graph = (AdjMatGraph) createUDGByYourHand();
Depth_First_Search.DFSTraverse(DNG_Graph);
Breadth_First_Search.BFSTraverse(DNG_Graph);
} 输出为:
图的深度优先遍历序列为: A B C D E F G H I
图的广度优先遍历序列为: A B F C G I E D H

  五、(举例)邻接表的深度优先遍历和广度优先遍历

    public static void main(String[] args) throws Exception {
AdjListGraph aListGraph = new AdjListGraph();
aListGraph.createGraph();
System.out.println("该类型的图已经创建完成!");
System.out.println("顶点数组下标为2的第一个邻接点的数组下标是: " + aListGraph.firstAdjvex(2));
int numOfV2 = aListGraph.firstAdjvex(2);
System.out.println("顶点V2的第一个邻接点是: " + aListGraph.getVex(numOfV2));
System.out.println("顶点数组下标为2的相对于顶点数组下标为0的下一个邻接点的数组下标是: " + aListGraph.nextAdjvex(2, 0));
int numOfV2toV0next = aListGraph.nextAdjvex(2, 0);
System.out.println("顶点V2相对于V0的邻接点是: " + aListGraph.getVex(numOfV2toV0next));
Depth_First_Search.DFSTraverse(aListGraph);
Breadth_First_Search.BFSTraverse(aListGraph);
} 输出为:
请输入图的类型代号(UDG(无向图)、DG(有向图)、UDN(无向网)、DN(有向网)):
UDG
请分别输入图的顶点数,图的边数:
5 6
请分别输入图的各个顶点:
V0 V1 V2 V3 V4
请输入各个边的两个顶点(第一个输入是弧尾,第二个输入是弧头):
V0 V4
V1 V2
V1 V0
V2 V3
V2 V0
V3 V4
该类型的图已经创建完成!
顶点数组下标为2的第一个邻接点的数组下标是: 0
顶点V2的第一个邻接点是: V0
顶点数组下标为2的相对于顶点数组下标为0的下一个邻接点的数组下标是: 3
顶点V2相对于V0的邻接点是: V3
图的深度优先遍历序列为: V0 V2 V3 V4 V1
图的广度优先遍历序列为: V0 V2 V1 V4 V3

数据结构(三十二)图的遍历(DFS、BFS)的更多相关文章

  1. 图的遍历[DFS][BFS]

    #include<iostream> #include<iostream> #include<cstring> #include<queue> #inc ...

  2. COJ968 WZJ的数据结构(负三十二)

    WZJ的数据结构(负三十二) 难度级别:D: 运行时间限制:5000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给你一棵N个点的无根树,边上均有权值,每个点上有 ...

  3. 三十二、Java图形化界面设计——布局管理器之CardLayout(卡片布局)

    摘自 http://blog.csdn.net/liujun13579/article/details/7773945 三十二.Java图形化界面设计--布局管理器之CardLayout(卡片布局) ...

  4. [COJ0968]WZJ的数据结构(负三十二)

    [COJ0968]WZJ的数据结构(负三十二) 试题描述 给你一棵N个点的无根树,边上均有权值,每个点上有一盏灯,初始均亮着.请你设计一个数据结构,回答M次操作. 1 x:将节点x上的灯拉一次,即亮变 ...

  5. 图的数据结构的实现与遍历(DFS,BFS)

    //图的存储结构:const int MAXSIZE = 10;//邻接矩阵template<class T>class MGraph {public:    MGraph(T a[], ...

  6. NeHe OpenGL教程 第三十二课:拾取游戏

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  7. Java进阶(三十二) HttpClient使用详解

    Java进阶(三十二) HttpClient使用详解 Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们 ...

  8. 微信小程序把玩(三十二)Image API

    原文:微信小程序把玩(三十二)Image API 选择图片时可设置图片是否是原图,图片来源.这用的也挺常见的,比如个人中心中设置头像,可以与wx.upLoadFile()API使用 主要方法: wx. ...

  9. Bootstrap <基础三十二>模态框(Modal)插件

    模态框(Modal)是覆盖在父窗体上的子窗体.通常,目的是显示来自一个单独的源的内容,可以在不离开父窗体的情况下有一些互动.子窗体可提供信息.交互等. 如果您想要单独引用该插件的功能,那么您需要引用  ...

  10. JAVA之旅(三十二)——JAVA网络请求,IP地址,TCP/UDP通讯协议概述,Socket,UDP传输,多线程UDP聊天应用

    JAVA之旅(三十二)--JAVA网络请求,IP地址,TCP/UDP通讯协议概述,Socket,UDP传输,多线程UDP聊天应用 GUI写到一半电脑系统挂了,也就算了,最多GUI还有一个提示框和实例, ...

随机推荐

  1. CDH集群的时间同步--简要配置要求

    每个节点执行ntpstat 和 timedatectl 都显示同步并且时间相同,那么CDH才能正常使用.每次ntp服务同步到外部授时中心都要一段时间(5~10分钟),只有当NTP server(nod ...

  2. nodeJs环境添加代理

    目的:实现前后端分离,前端减少路径请求的所需的路由文件: 第一步:安装http代理中间件 npm install http-proxy-middleware --save 第二步: express文件 ...

  3. uC/OS-III 时钟节拍(一)

    时钟节拍就是操作系统的时基,操作系统要实现时间上的管理,必须依赖于时基(时基即时间基准,操作系统的基准时钟). uC/OS-III时钟节拍的实现过程 时钟节拍就是系统以固定的频率产生中断(时基中断), ...

  4. Docker系列(一):容器监控工具Weave Scope安装

    项目进行容器化之后,配套的基础设施包括监控.编排.管理等都需要进行一并完善.这里也是自己一边学习一边进行记录. Weave Scope 的最大特点是会自动生成一张 Docker 容器地图,让我们能够直 ...

  5. JS调用activeX实现浏览本地文件夹功能 wekit内核只需要<input type="file" id="files" name="files[]" webkitdirectory/>即可,IE内核比较麻烦

    研究了一天,js访问本地文件本身是不可能的,只能借助于插件.植入正题,IE仅支持ActiveX插件. function openDialog() { try { var Message = " ...

  6. SSM相关知识

    1.SpringMVC的工作流程? 1. 用户发送请求至前端控制器DispatcherServlet 2. DispatcherServlet收到请求调用HandlerMapping处理器映射器. 3 ...

  7. PHP--网络协议相关知识

    HTTP状态码 HTTP状态码(HTTP Status Code)是用以表示网页服务器HTTP响应状态的3位数字代码. HTTP状态码主要有5种,代表5种不同类型的响应: 1xx:信息性状态码,代表接 ...

  8. [Note] Windows 10 Python 3.6.4 安装scrapy

    直接使用pip install安装时会在安装Twisted出错,以下主要是解决Twisted的安装问题 1. 安装wheel pip install wheel 2. 安装Twisted 在Pytho ...

  9. Java匹马行天下之教你用学汉语式方法学编程语言

    Java匹马行天下之教你用学汉语式方法学编程语言 前言: 前段时间接连更新了带小白从入门到了解的几篇博客: <Java匹马行天下之编程常识知多少> <Java匹马行天下之走进编程的殿 ...

  10. Python+Tornado+Tampermonkey 获取某讯等主流视频网站的会员视频解析播放

    近期,<哪吒之魔童降世>在各大视频软件可以看了,然而却是一贯的套路,非会员谢绝观看!!!只能从国内那些五花八门的视频网站上找着看了,或者通过之前本人说的 Chrome 的油猴插件,传送门  ...