邻接表表示的图的广度优先遍历-Breadth First Search Graph

Breadth First Search Graph

eryar@163.com

一、简介

广度优先遍历类似于树的按层次遍历过程。

假设从图中某顶点V出发,在访问了V之后依次访问V的各个未曾访问过的邻接顶点,然后分别从这些邻接点出发依次访问它们的邻接点,并使“先被访问的顶点的邻接点”先于“后被访问的顶点的邻接点”被访问,直到图中所有已被访问的顶点的邻接点都被访问到。到此时图中尚有未被访问的顶点,则另选图中一个未曾访问的顶点作为始点,重复上述过程,直到图中所有顶点都被访问到为止。换言之,广度优先遍历图的过程是以V为起始点,由近至远,依次访问和V有路径相通且路径长度为1,2,……的顶点。

为了顺序访问路径长度为1,2,……的顶点,需要利用队列的数据特性:先进先出来存储已被访问的路径长度为1,2,……的顶点。

二、C++实现


  1: //------------------------------------------------------------------------------
  2: //	Copyright (c) 2012 eryar All Rights Reserved.
  3: //
  4: //		File    : Main.cpp
  5: //		Author  : eryar@163.com
  6: //		Date    : 2012-8-25 17:11
  7: //		Version : 0.1v
  8: //
  9: //	Description : Use Adjacency List data structure to store Digraph.
 10: //
 11: //==============================================================================
 12:
 13: #include <vector>
 14: #include <queue>
 15: #include <string>
 16: #include <iostream>
 17: using namespace std;
 18:
 19: struct SVertexNode
 20: {
 21:     bool          bIsVisited;
 22:     string        data;
 23:     vector<int> vecLoc;
 24: };
 25:
 26: typedef struct SEdge
 27: {
 28:     int iInitialNode;
 29:
 30:     int iTerminalNode;
 31:
 32: }Edge;
 33:
 34: typedef struct SGraph
 35: {
 36:     int iVertexNum;
 37:     int iEdgeNum;
 38:     vector<SVertexNode> vecVertex;
 39: }Graph;
 40:
 41: ///////////////////////////////////////////////////////////////////////////////
 42: // Functions of Graph
 43: void    Initialize(Graph& g, int v);
 44: Edge    MakeEdge(int v, int w);
 45: void    InsertEdge(Graph& g, const Edge& e);
 46: void    ShowGraph(const Graph& g);
 47: void    ClearVisitFlag(Graph& g);
 48:
 49: // Use Depth First Search method to Traverse the graph.
 50: void    DepthFirstSearch(Graph& g);
 51: void    DepthFirstSearch(Graph& g, int v);
 52:
 53: // Use Breadth First Search method to Traverse the graph.
 54: void    BreadthFirstSearch(Graph& g);
 55:
 56: ///////////////////////////////////////////////////////////////////////////////
 57: // Main function.
 58:
 59: int main(int agrc, char* argv[])
 60: {
 61:     Graph   aGraph;
 62:
 63:     // Initialize the graph.
 64:     Initialize(aGraph, 4);
 65:
 66:     // Insert some edges to make graph.
 67:     InsertEdge(aGraph, MakeEdge(0, 1));
 68:     InsertEdge(aGraph, MakeEdge(0, 2));
 69:     InsertEdge(aGraph, MakeEdge(2, 3));
 70:     InsertEdge(aGraph, MakeEdge(3, 0));
 71:
 72:     // Show the graph.
 73:     ShowGraph(aGraph);
 74:
 75:     // DFS traverse the graph.
 76:     DepthFirstSearch(aGraph);
 77:
 78:     // BFS traverse the graph.
 79:     BreadthFirstSearch(aGraph);
 80:
 81:     return 0;
 82: }
 83:
 84: ///////////////////////////////////////////////////////////////////////////////
 85:
 86: /**
 87: * brief	Initialize the graph.
 88: *
 89: *       v: vertex number of the graph.
 90: */
 91: void Initialize( Graph& g, int v )
 92: {
 93:     char    szData[6];
 94:     SVertexNode node;
 95:
 96:     g.iVertexNum    = v;
 97:     g.iEdgeNum      = 0;
 98:
 99:     for (int i = 0; i < v; i++)
100:     {
101:         sprintf(szData, "V%d", i+1);
102:         node.data   = szData;
103:         node.bIsVisited = false;
104:         g.vecVertex.push_back(node);
105:     }
106: }
107:
108: /**
109: * brief	Make an edge by initial node and terminal node.
110: */
111: Edge MakeEdge( int v, int w )
112: {
113:     Edge    e;
114:
115:     e.iInitialNode  = v;
116:     e.iTerminalNode = w;
117:
118:     return e;
119: }
120:
121: /**
122: * brief	Insert an edge to the graph.
123: */
124: void InsertEdge( Graph& g, const Edge& e )
125: {
126:     g.vecVertex.at(e.iInitialNode).vecLoc.push_back(e.iTerminalNode);
127:
128:     // If the graph is Undigraph, need do something here...
129:     //g.vecVertex.at(e.iTerminalNode).vecLoc.push_back(e.iInitialNode);
130:
131:     g.iEdgeNum++;
132: }
133:
134: /**
135: * brief	Show the graph.
136: */
137: void ShowGraph( const Graph& g )
138: {
139:     cout<<"Show the graph: "<<endl;
140:
141:     for (int i = 0; i < g.iVertexNum; i++)
142:     {
143:         cout<<"Node "<<i<<"("<<g.vecVertex.at(i).data<<")";
144:
145:         for (int j = 0; j < g.vecVertex.at(i).vecLoc.size(); j++)
146:         {
147:             cout<<"->"<<g.vecVertex.at(i).vecLoc.at(j);
148:         }
149:
150:         cout<<endl;
151:     }
152: }
153:
154: void ClearVisitFlag( Graph& g )
155: {
156:     for (int i = 0; i < g.iVertexNum; i++)
157:     {
158:         g.vecVertex.at(i).bIsVisited    = false;
159:     }
160: }
161:
162: void DepthFirstSearch( Graph& g )
163: {
164:     cout<<"Depth First Search the graph:"<<endl;
165:
166:     for (int i = 0; i < g.iVertexNum; i++)
167:     {
168:         if (!(g.vecVertex.at(i).bIsVisited))
169:         {
170:             DepthFirstSearch(g, i);
171:         }
172:     }
173: }
174:
175: void DepthFirstSearch(Graph& g, int v)
176: {
177:     int     iAdjacent   = 0;
178:     SVertexNode node    = g.vecVertex.at(v);
179:
180:     // Visit the vertex and mark it.
181:     cout<<g.vecVertex.at(v).data<<endl;
182:     g.vecVertex.at(v).bIsVisited = true;
183:
184:     // Visit the adjacent vertex.
185:     for (int i = 0; i < node.vecLoc.size(); i++)
186:     {
187:         iAdjacent   = node.vecLoc.at(i);
188:
189:         if (!(g.vecVertex.at(iAdjacent).bIsVisited))
190:         {
191:             DepthFirstSearch(g, iAdjacent);
192:         }
193:     }
194:
195: }
196:
197: void BreadthFirstSearch( Graph& g )
198: {
199:     SVertexNode         node;
200:     queue<SVertexNode> visitedNodes;
201:
202:     cout<<"Breadth First Search the graph:"<<endl;
203:
204:     ClearVisitFlag(g);
205:
206:     for (int i = 0; i < g.iVertexNum; i++)
207:     {
208:         node    = g.vecVertex.at(i);
209:
210:         if (!node.bIsVisited)
211:         {
212:             // Visit it.
213:             cout<<node.data<<endl;
214:
215:             // Set visite flag.
216:             g.vecVertex.at(i).bIsVisited = true;
217:
218:             // Enqueue.
219:             visitedNodes.push(node);
220:
221:             while (!visitedNodes.empty())
222:             {
223:                 node    = visitedNodes.front();
224:
225:                 visitedNodes.pop();
226:
227:                 for (int j = 0; j < node.vecLoc.size(); j++)
228:                 {
229:                     if (!g.vecVertex.at(j).bIsVisited)
230:                     {
231:                         cout<<g.vecVertex.at(j).data<<endl;
232:
233:                         g.vecVertex.at(j).bIsVisited    = true;
234:
235:                         visitedNodes.push(g.vecVertex.at(j));
236:                     }
237:                 }
238:             }
239:         }
240:     }
241: }
242: 

 

三、程序输出

程序的数据来源为原先用邻接表生成图的程序,可以根据需要自定义数据来验证程序的正确性。


  1: Show the graph:
  2: Node 0(V1)->1->2
  3: Node 1(V2)
  4: Node 2(V3)->3
  5: Node 3(V4)->0
  6: Depth First Search the graph:
  7: V1
  8: V2
  9: V3
 10: V4
 11: Breadth First Search the graph:
 12: V1
 13: V2
 14: V3
 15: V4
 16: Press any key to continue
 17: 

四、结论

由上程序可知,广度优先遍历图的过各实质上也是查找邻接点的过程。因此,广度优先遍历和深度优先遍历时间复杂度相同,两者不同之处仅仅在于对顶点的访问顺序不同。

时间: 2024-09-20 20:25:12

邻接表表示的图的广度优先遍历-Breadth First Search Graph的相关文章

深度优先遍历DFS用邻接表表示的图

深度优先遍历用邻接表表示的图 DFS the Adjacency List Graph eryar@163.com 一.简介 创建了图之后,我们希望从图中某个顶点出发访遍图中其余顶点,且使每个顶点仅被访问一次.这一过程就是图的遍历(Traversing Graph).图的遍历算法是求解图的连通性问题.拓朴排序和求解关键路径等算法的基础. 深度优先搜索(Depth First Search)是一种递归的遍历方法.其过程为从图中任意一顶点出发,访问与其相连接的未被访问的顶点.因此,遍历图的过程实质上

算法研究:图的广度优先遍历

图的遍历和树的遍历类似,我们希望从图中某一顶点出发访遍图中其余顶点,且使每一个顶点仅被访问一次,这一过程 就叫做图的遍历(Traverse Graph). 图的遍历方法一般有两种,第一种是我们在前面讲过的<深度优先遍历 (Depth First Search)>,也有称为深度优先搜索,简称为DFS.第二种是广度优先遍历(Breadth  First Search), 也有称为广度优先搜索,简称为BFS.我们在<队列与广度优先搜索>中已经较为详细地讲述了广度优先搜索的策略,这里 不再

基于Java实现的图的广度优先遍历算法_java

本文以实例形式讲述了基于Java的图的广度优先遍历算法实现方法,具体方法如下: 用邻接矩阵存储图方法: 1.确定图的顶点个数和边的个数 2.输入顶点信息存储在一维数组vertex中 3.初始化邻接矩阵: 4.依次输入每条边存储在邻接矩阵arc中 输入边依附的两个顶点的序号i,j: 将邻接矩阵的第i行第j列的元素值置为1: 将邻接矩阵的第j行第i列的元素值置为1: 广度优先遍历实现: 1.初始化队列Q 2.访问顶点v:visited[v]=1;顶点v入队Q; 3.while(队列Q非空) v=队列

数据结构实践——操作用邻接表存储的图

本文是针对[数据结构基础系列(7):图]的实践. [项目 - 操作用邻接表存储的图] 假设图G采用邻接表存储,分别设计实现以下要求的算法: (1)输出出图G中每个顶点的出度: (2)求出图G中出度最大的一个顶点,输出该顶点编号: (3)计算图G中出度为0的顶点数: (4)判断图G中是否存在边<i,j>. 利用下图作为测试用图,输出结果. 提示:(1)分别设计函数实现算法:(2)不要全部实现完再测试,而是实现一个,测试一个:(3)请利用图算法库. [参考解答] #include <stdi

图的广度优先遍历算法

前言 广度优先遍历算法是图的另一种基本遍历算法,其基本思想是尽最大程度辐射能够覆盖的节点,并对其进行访问.以迷宫为例,深度优先搜索更像是一个人在走迷宫,遇到没有走过就标记,遇到走过就退一步重新走:而广度优先搜索则可以想象成一组人一起朝不同的方向走迷宫,当出现新的未走过的路的时候,可以理解成一个人有分身术,继续从不同的方向走,,当相遇的时候则是合二为一(好吧,有点扯了). 广度优先遍历算法的遍历过程 仍然以上一篇图的深度优先遍历算法的例子进行说明,下面是广度优先遍历的具体过程: 从起点0开始遍历

C++实现图的邻接表存储和广度优先遍历实例分析_C 语言

本文实例讲述了C++实现图的邻接表存储和广度优先遍历方法.分享给大家供大家参考.具体如下: 示例:建立如图所示的无向图 由上图知,该图有5个顶点,分别为a,b,c,d,e,有6条边. 示例输入(按照这个格式输入): 5 6 abcde 0 1 0 2 0 3 2 3 2 4 1 4 输入结束(此行不必输入) 注:0 1表示该图的第0个顶点和第1个定点有边相连,如上图中的a->b所示       0 2表示该图的第0个顶点和第2个定点有边相连,如上图中的a->c所示       2 3表示该图的

图的深度优先遍历算法

前言 图的遍历与前面文章中的二叉树遍历还是存在很大区别的.所谓图的遍历指的是从图中的某一个顶点出发访问图中的其余顶点,并且需要保证每个顶点只被访问一次.由于图比二叉树复杂得多,所以前面二叉树的遍历算法在图中是行不通的.因为对于任意一个顶点来讲,都可能与其余的顶点发生连接.如果不对访问的顶点做一些处理,出发重复访问的几率是很高的.因此,一个基本思想是设置一个标记数组,主要用于标记已经被访问过的顶点.图的遍历算法主要有两种:深度优先遍历和广度优先遍历.本篇文章主要介绍的是深度优先遍历算法. 深度优先

Java实现利用广度优先遍历(BFS)计算最短路径的方法_java

本文实例讲述了Java实现利用广度优先遍历(BFS)计算最短路径的方法.分享给大家供大家参考.具体分析如下: 我们用字符串代表图的顶点(vertax),来模拟学校中Classroom, Square, Toilet, Canteen, South Gate, North Gate几个地点,然后计算任意两点之间的最短路径. 如下图所示: 如,我想从North Gate去Canteen, 程序的输出结果应为: BFS: From [North Gate] to [Canteen]: North Ga

图的深度优先遍历

/* 这是一个图的的深度优先搜索,我参考清华大学 c 语言版 1997年 4月第一版    教材中没有构图的函数CreatGraph(),FirstAdjVex()和NextAdjvex(),我在这里写出来了 .    图的存储结构采用邻接表存储.不过构图时的输入比较复杂,请读者认真读以下说明    说明:    假设有顶点 a(1) b(2) c(3) d(4) e(5)    图如下:                  (1)                  (a)