BFS

BFS是广度优先搜索算法,是图的一种搜索算法,当然也可以用作其它的地方。BFS是一种盲目搜索算法,其目的是系统的展开并检查途中的节点。而且如果图是非加权的(各个边的长度相等),那么它找到的第一个解是距离根节点的边数目一定最少。但如果图是加权图,那么边数目最少并不代表路径最少,因此找到的解不一定是最佳解。而且BFS的空间复杂度是:O(V+E);时间复杂度是O(V+E);其中V是图中的节点数,V是图的边数。可以参考维基百科中所说的http://zh.wikipedia.org/wiki/广度(宽度)优先搜索法

在讨论BFS的具体实现之前,我们先回顾下图的表示方式:

1.邻接矩阵的表示方法

        A. 用邻接矩阵表示顶点间的关系(即边)

        B.用一个顺序表来存储顶点信息

对于加权图和非加权图,它们的邻接矩阵的表示方式不一样;对于非加权图,如果两顶点之间相连,那么它们对应的邻接矩阵的边的值为1,否则为0;而加权图的邻接矩阵中的元素的值是两顶点之间边的权值,如果不相连,则为0

具两个例子来表示

对于非加权图的无向图和有向图:

《BFS》

对于加权图:

《BFS》

上面的两张图是copy别人的,对于邻接矩阵的建立就比较简单了,下面我们给出相应的代码:


#define MaxVertexNum 100 // 最大顶点个数,可以按需求定义
typedef char VertexType; // 顶点类型
typedef int EdgeType; //边的类型

typedef struct {
	VertexType vertex[MaxVertexNum]; //保存顶点的有序表
	EdgeType edge[MaxVertexNum][MaxVertexNum];//邻接矩阵(二维的)
	int e;// 边的数量
	int v;// 顶点的数量
}Mgraph;

void create_mgraph( Mgraph *G)
{
	int i,j,k,w;
	//memset(G, 0, sizeof(Mgraph));
	scanf(“%d%d”, &G->v, &G->e);// 输入顶点数和边数
	while(i =0; i < G->v; i++)
		G->vertex[i] = getchar(); //输入顶点的信息
	for(j =0; j < G->v; j++)
		for(k =0; k< G->v; k++)
			G->edge[j][k] = 0;
	for( k =0; k<G->e; k++)
	{
		scanf(“%d%d%d”, &i,&j,&w);
		G->edge[i][j] = w;
		G->edge[j][i] = w; // 对于无向图i->j 和j->i的边是一样的
} // end for 
} // create_mgraph

2.邻接表表示

邻接表是由两部分组成的,一是图中所有顶点的数组,而是与每个顶点相连的所有顶点组成的链表。

《BFS》

邻接表的形式说明及其建表算法

typedef char VertexType; // 顶点类型
typedef int ArrType; //顶点在数组中位置的类型
typedef struct node{//边表结点
       int adjvex; //邻接点域
       struct node *next; //链域
     //若要表示边上的权,则应增加一个数据域
   }EdgeNode;
     typedef struct vnode{ //顶点表结点
       VertexType vertex; //顶点域
			  ArrType num; //顶点在数组(顺序表)中的位置
       EdgeNode *firstedge;//边表头指针
    }VertexNode;
     typedef VertexNode AdjList[MaxVertexNum];//AdjList是邻接表类型
      typedef struct{
       AdjList adjlist;//邻接表
       int v,e; 图中当前顶点数和边数 
   }ALGraph; //对于简单的应用,无须定义此类型,可直接使用AdjList类型。
void create_ALGraph(ALGraph * G)
{
    int i, j,k;
    EdgeNode *temp = NULL;
    scanf("%d%d", &G->v,&G->e);
    char d;
    while((d = getchar())!='\n'&&d != EOF);// 清空输入流
    for(i =0; i < G->v; i++) // 输入顶点信息
    {
        G->adjlist[i].vertex = getchar();
        G->adjlist[i].vertnum = i;
        G->adjlist[i].firstedge = NULL;
        }//end for
    for(k = 0; k < G->e; k++) //输入邻接链表信息
    {
        scanf("%d%d",&i,&j);// 输入边的两个顶点
        temp = (EdgeNode*)malloc(sizeof(EdgeNode));
        temp->adjnum = j;
        temp->next = G->adjlist[i].firstedge;//从头部插入节点
        G->adjlist[i].firstedge = temp;//建立i个顶点与j个顶点的链表关系

        temp = (EdgeNode*)malloc(sizeof(EdgeNode));
        temp->adjnum = i;
        temp->next = G->adjlist[j].firstedge;//从头部插入节点
        G->adjlist[j].firstedge = temp;//建立i个顶点与j个顶点的链表关系
        }//end for

}//end createALGraph

注意上面的红色部分的标注,它的意思是指邻接表中的链表采用的是头部插入的方式插入节点的。因为邻接表中的链表的节点顺序可以是任意的,因此采取头部或尾部插入节点是一样的。而且头部插入方法无需查找链表尾,效率较高。

BFS算法的分析:

BFS首先从根节点进行访问,并且记录根节点的所有邻居节点(可以用队列实现),然后再一次对其每个邻居节点进行重复的处理。对已经访问的节点进行标识,标识的方法也可以采用队列的方式或者其他的方式。

BFS的非递归C++的实现:

BFS
是为了遍历访问所有的顶点,因此用邻接表表示图更适合做
BFS
。下面就其
C++
的实现进行分析;(和上面的无向图的邻接表建立方法对应)


void visit(VertexNode *cur)
{
    if(cur == NULL)
        return;
    cout<<cur->vertex<<endl;
    }
void BFS(ALGraph *G)
{
    if(NULL == G)
        return;
    int visited[MaxVertexNum];
    memset(visited, 0, MaxVertexNum*sizeof(int));
    queue<VertexNode*> unvisited;
    unvisited.push(&G->adjlist[0]);
    while(!unvisited.empty())
    {
        VertexNode *cur = unvisited.front();
        if(visited[cur->vertnum] == 0)
        {
            visit(cur);
            visited[cur->vertnum] = 1;
            }//end if
        EdgeNode *temp = cur->firstedge;
        while(temp != NULL)
        {
            if(visited[temp->adjnum]== 0)
                unvisited.push(&G->adjlist[temp->adjnum]);
            temp = temp->next;
            }//end while
        unvisited.pop();
        }//end while
    return;
}//end BFS

int main()
{
    ALGraph G;
    cout<<sizeof(G)<<endl;
    create_ALGraph(&G);
    BFS(&G);
    return 0;
}

最终的运行结果:


《BFS》

    原文作者:BFS
    原文地址: https://blog.csdn.net/susershine/article/details/16897893
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞