图算法三之BFS

来源:互联网 发布:淘宝佣金是多少 编辑:程序博客网 时间:2024/05/01 11:39

   如果说图的深度优先遍历类似树的前序遍历, 那么图的广度优先遍历就类似于树的层序遍历了,其实我就是按照树的层次遍历来理解图的BFS,因为这样容易记忆还方便理解

BFS也贴个图吧

代码也不长,感觉和DFS一样,都是侧重于理解,理解了代码就能写出来了

先是邻接矩阵的BFS

void MGraphBFS(int i,struct MGraph *graph){queue<int> queue;flag[i] = 1;queue.push(i);while(queue.size()){int current = queue.front();printf("%d ",current);queue.pop();for(i=0;i<graph->numVertexes;i++){if(!flag[i]&&graph->arc[current][i]!=INFINITY){flag[i] = 1;queue.push(i);}}}}
然后是邻接表的BFS

void LGraphBFS(int i,struct LGraph *graph){queue<int> queue;flag[i] = 1;queue.push(i);while(queue.size()){int current = queue.front();printf("%d ",current);queue.pop();struct EdgeNode *e = graph->adjList[current].firstarc;while(e){if(!flag[e->adjex])  {flag[e->adjex] = 1;queue.push(e->adjex);}e = e->next;}}}
最后总结一下,感觉大话数据结构总结得挺好,就copy了

    对比图的深度优先遍历与广度优先遍历算法,你会发现,它们在时间复杂度上是一样的,不同之处仅仅在于对顶点访问的顺序不同。可见两者在全图遍历上是没有优劣之分的,只是视不同的情况选择不同的算法。
    不过如果图顶点和边非常多,不能在短时间内遍历完成,遍历的目的是为了寻找合适的顶点,那么选择哪种遍历就要仔细斟酌了。深度优先更适合目标比较明确,以找到目标为主要目的的情况,而广度优先更适合在不断扩大遍历范围时找到相对最优解的情况。
    这里还要再多说几句,对于深度和广度而言,已经不是简单的算法实现问题,完全可以上升到方法论的角度。你求学是博览群书、不求甚解,还是深钻细研、鞭辟入里;你旅游是走马观花、蜻蜓点水,还是下马看花、深度体验;你交友是四海之内皆兄弟,还是人生得一知己足矣……其实都无对错之分,只视不同人的理解而有了不同的诠释。我个人觉得深度和广度是既矛盾叉统一的两个方面,偏颇都不可取,还望大家自己慢慢体会。


最后,总的代码如下:

#include <stdio.h>#include <stdlib.h>#include <iostream>#include <queue>using namespace std;#define MAXN 100#define INFINITY 65536bool flag[MAXN];struct MGraph{int numEdges,numVertexes;int vex[MAXN];int arc[MAXN][MAXN];};struct EdgeNode{int weight;int adjex;struct EdgeNode *next;};struct VexNode{int data;struct EdgeNode *firstarc;};struct LGraph{int numEdges,numVertexes;struct VexNode adjList[MAXN];};void createMGraph(struct MGraph *graph){printf("请输入图的总顶点数和边数:\n");scanf("%d%d",&graph->numVertexes,&graph->numEdges);int i,j,k;for(i=0;i<graph->numVertexes;i++){for(j=0;j<graph->numVertexes;j++){graph->arc[i][j] = INFINITY; }}for(i=0;i<graph->numVertexes;i++){graph->vex[i] = i;}for(k=0;k<graph->numEdges;k++){printf("请输入(vi,vj)的下标i和j\n");scanf("%d%d",&i,&j);graph->arc[i][j] = graph->arc[j][i] = 1;}}//对存储结构为邻接矩阵的图进行BFSvoid MGraphBFS(int i,struct MGraph *graph){queue<int> queue;flag[i] = 1;queue.push(i);while(queue.size()){int current = queue.front();printf("%d ",current);queue.pop();for(i=0;i<graph->numVertexes;i++){if(!flag[i]&&graph->arc[current][i]!=INFINITY){flag[i] = 1;queue.push(i);}}}}void createLGraph(LGraph *graph){printf("请输入图的顶点数和边数\n");scanf("%d%d",&graph->numVertexes,&graph->numEdges);int i,j,k;for(i=0;i<graph->numVertexes;i++){graph->adjList[i].data = i;graph->adjList[i].firstarc = NULL;}for(k=0;k<graph->numEdges;k++){printf("请输入(vi,vj)的下标i和j\n");scanf("%d%d",&i,&j);struct EdgeNode *e = (struct EdgeNode *)malloc(sizeof(struct EdgeNode));e->adjex = j;e->next = graph->adjList[i].firstarc;graph->adjList[i].firstarc = e;e = (struct EdgeNode *)malloc(sizeof(struct EdgeNode));e->adjex = i;e->next = graph->adjList[j].firstarc;graph->adjList[j].firstarc = e;}}//对存储结构为邻接表的图进行BFSvoid LGraphBFS(int i,struct LGraph *graph){queue<int> queue;flag[i] = 1;queue.push(i);while(queue.size()){int current = queue.front();printf("%d ",current);queue.pop();struct EdgeNode *e = graph->adjList[current].firstarc;while(e){if(!flag[e->adjex])  {flag[e->adjex] = 1;queue.push(e->adjex);}e = e->next;}}}int main(){MGraph graph;createMGraph(&graph);   MGraphBFS(0,&graph);   //都是建立的连通图,所以不需要循环了,只需要从0开始调用int i;for(i=0;i<MAXN;i++) flag[i] = 0;LGraph lgraph;createLGraph(&lgraph);LGraphBFS(0,&lgraph);return 0;}


如果文章有什么错误或者有什么建议,欢迎提出,大家共同交流,一起进步

文章转载请注明出处,请尊重知识产权

0 0