一、广度优先搜索应用举例:计算网络跳数
图结构在解决许多网络相关的问题时直到了重要的作用。
比如,用来确定在互联网中从一个结点到另一个结点(一个网络到其他网络的网关)的最佳路径。一种建模方法是采用无向图,其中顶点表示网络结点,边代表结点之间的联接。使用这种模型,可以采用广度优先搜索来帮助确定结点间的最小跳数。
如图1所示,该图代表Internet中的6个网络结点。以node1作为起点,有不止1条可以通往node4的路径。<node1,node2,node4>,<node1,node3,node2,node4>,<node1,node3,node5,node4>都是可行的路径。广度优先搜索可以确定最短路径选择,即<node1,node2,node4>,一共只需要两跳。

我们以bfs作为广度优先搜索的函数名(见示例1及示例2)。该函数用来确定互联网中两个结点之间的最小跳数。这个函数有3个参数:graph是一个图,在这个问题中就代表整个网络;start代表起始的顶点;hops是返回的跳数链表。函数bfs会修改图graph,因此,如果有必要的话在调用该函数前先对图创建拷贝。另外,hops中返回的是指向graph中实际顶点的指针,因此调用者必须保证只要访问hops,graph中的存储空间就必须保持有效。
graph中的每一个顶点都是一个BfsVertex类型的结构体(见示例1),该结构体有3个成员:data是指向图中顶点的数据域指针,color在搜索过程中维护顶点的颜色,hops维护从起始顶点开始到目标顶点的跳数统计。
match函数是由调用者在初始化graph时作为参数传递给graph_init的。match函数应该只对BfsVertex结构体中的data成员进行比较。
bfs函数将按照前面介绍过的广度优先搜索的方式来计算。为了记录到达每个顶点的最小跳数,将每个顶点的hop计数设置为与该顶点邻接的顶点的hop计数加1。对于每个发现的顶点都这样处理,并将其涂成灰色。每个顶点的颜色和跳数信息都由邻接表结构链表中的BfsVertex来维护。最后,加载hops中所有跳数未被标记为-1的顶点。这些就是从起始顶点可达的顶点。
bfs的时间复杂度为O(V+E),这里V代表图中的顶点个数,E是边的个数。这是因为初始化顶点的颜色属性以及确保起始顶点存在都需要O(V)的运行时间,广度优先搜索中的循环的复杂度是O(V+E),加载跳数统计链表的时间为O(V)。
示例1:广度优先搜索的头文件
/*bfs.h*/
#ifndef BFS_H
#define BFS_H
#include "graph.h"
#include "list.h"
/*定义广度优先搜索中的顶点数据结构*/
typedef struct BfsVertex_
{
void *data;
VertexColor color;
int hops;
}BfsVertex;
/*函数接口定义*/
int bfs(Graph *graph, BfsVertex *start, List *hops);
#endif // BFS_H
示例2:广度优先搜索的实现
/*bfs.c*/
#include <stdlib.h>
#include "bfs.h"
#include "graph.h"
#include "list.h"
#include "queue.h"
/*bfs */
int bfs(Graph *graph, BfsVertex *start, List *hops)
{
Queue queue;
AdjList *adjlist, *clr_adjlist;
BfsVertex *clr_vertex, *adj_vertex;
ListElmt *element, *member;
/*初始化图中的所有结点为广度优先结点*/
for(element = list_head(&graph_adjlists(graph)); element != NULL; element = list_next(element))
{
clr_vertex = ((AdjList *)list_data(element))->vertex;
if(graph->match(clr_vertex,start))
{
/*初始化起始顶点*/
clr_vertex->color = gray;
clr_vertex->hops = 0;
}
else
{
&nb


2845

被折叠的 条评论
为什么被折叠?



