深度优先搜索(Breadth  First Search),类似于树的层序遍历,搜索模型是队列,还是以下面的无向图为例:

实验环境是Ubuntu 14.04 x86

伪代码实现如下:

其中u v 的先辈或父母。

BFS(G, s)

for each vertex u ∈ V [G] - {s}
do color[u] ← WHITE
d[u] ← ∞
π[u] ← NIL //除了源顶点s之外,第1-4行置每个顶点为白色,置每个顶点u的d[u]为无穷大,置每个顶点的父母为NIL。
color[s] ← GRAY // 将源顶点s置为灰色,这是因为在过程开始时,源顶点已被发现。
d[s] ← 0
π[s] ← NIL //将源顶点的父顶点置为NIL。
Q ← Ø
ENQUEUE(Q, s) //第8、9行,初始化队列Q,使其仅含源顶点s。
while Q ≠ Ø
do u ← DEQUEUE(Q) //确定队列头部Q头部的灰色顶点u,并将其从Q中去掉。
for each v ∈ Adj[u] //for循环考察u的邻接表中的每个顶点v
do if color[v] = WHITE
then color[v] ← GRAY
d[v] ← d[u] + 1
π[v] ← u //u记为该顶点的父母
ENQUEUE(Q, v) //插入队列中
color[u] ← BLACK

队列推荐使用链式队列。

邻接表实现:

#include <stdio.h>
#include <malloc.h> #define MAX_VERTEX_NUM 50 typedef char vertexType;
typedef int edgeType;
typedef int QueueElemType; /* 边表 */
typedef struct ArcNode
{
int adjIndex;
struct ArcNode *nextArc;
edgeType weight;
}ArcNode; /* 顶点表 */
typedef struct VNode
{
vertexType data;
ArcNode *firstArc;
}VNode, AdjList[MAX_VERTEX_NUM]; /* 图结构 */
typedef struct
{
AdjList adjList;
int vexNum;
int edgeNum;
}ALGraph; typedef struct QueueNode
{
QueueElemType data;
struct QueueNode *next;
}QueueNode; typedef struct
{
QueueNode *front;
QueueNode *rear;
}LinkQueue; int visit[MAX_VERTEX_NUM] = {0}; void initLinkQueue(LinkQueue *queue)
{
QueueNode *head = (QueueNode*)malloc(sizeof(QueueNode));
if(head == NULL)
{
printf("malloc failed\n");
return;
} head->next = NULL;
queue->front = queue->rear = head; return;
} void insertLinkQueue(LinkQueue *queue, QueueElemType data)
{
QueueNode *newNode = (QueueNode *)malloc(sizeof(QueueNode));
if(NULL == newNode)
{
printf("malloc failed\n");
return;
} newNode->data = data;
newNode->next = NULL; queue->rear->next = newNode;
queue->rear = newNode; return;
} int deleteLinkQueue(LinkQueue *queue, QueueElemType *data)
{
QueueNode *p; if (queue->front == queue->rear)
{
printf("no element!\n");
return 0;
} p = queue->front->next;
*data = p->data; queue->front->next = p->next;
if (p == queue->rear)
{
queue->rear = queue->front;
} free(p);
return 1;
} void BFSTraverse(ALGraph G)
{
QueueElemType q;
LinkQueue queue;
ArcNode *adjEdge;
int index = 0; initLinkQueue(&queue); for (int i = 0; i < G.vexNum; i++)
{
if (!visit[i])
{
visit[i] = 1;
printf("%c ", G.adjList[i].data);
insertLinkQueue(&queue, i); while (deleteLinkQueue(&queue, &q))
{
adjEdge = G.adjList[q].firstArc;
while (adjEdge)
{
index = adjEdge->adjIndex; if (!visit[index])
{
visit[index] = 1;
printf("%c ", G.adjList[index].data); insertLinkQueue(&queue, index);
}
adjEdge = adjEdge->nextArc;
}
}
} } } void CreateALGraph(ALGraph *G)
{
int i, j, k;
ArcNode *e;
int c; printf("输入顶点数和边数:\n");
scanf("%d %d", &G->vexNum, &G->edgeNum);
setbuf(stdin, NULL); for (i = 0; i < G->vexNum; i++)
{
printf("输入顶点信息:\n");
scanf("%c", &G->adjList[i].data);
G->adjList[i].firstArc = NULL; while((c = getchar()) != '\n' && c != EOF);
} for (k = 0; k < G->edgeNum; k++)
{
printf("输入边(vi,vj)的顶点序号i,j:\n");
scanf("%d %d", &i, &j); while((c = getchar()) != '\n' && c != EOF); e = (ArcNode*)malloc(sizeof(ArcNode));
if (NULL == e)
{
return;
} e->adjIndex = j;
e->nextArc = G->adjList[i].firstArc;
G->adjList[i].firstArc = e; // double direction copy
e = (ArcNode *)malloc(sizeof(ArcNode));
if (NULL == e)
{
return;
}
e->adjIndex = i;
e->nextArc = G->adjList[j].firstArc;
G->adjList[j].firstArc = e;
}
} int main(int argc, char const *argv[])
{
ALGraph G;
CreateALGraph(&G); BFSTraverse(G);
return 0;
}

运行结果: A F B G E I C H D

邻接矩阵实现:

#include <stdio.h>
#include <malloc.h> #define MAX_VERTEX_NUM 50 typedef char vertexType;
typedef int edgeType;
typedef int QueueElemType; typedef struct
{
vertexType vexs[MAX_VERTEX_NUM];
edgeType arc[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
int vexNum;
int edgeNum;
}Graph; typedef struct QueueNode
{
QueueElemType data;
struct QueueNode *next;
}QueueNode; typedef struct
{
QueueNode *front;
QueueNode *rear;
}LinkQueue; int visit[MAX_VERTEX_NUM] = {0}; void initLinkQueue(LinkQueue *queue)
{
QueueNode *head = (QueueNode*)malloc(sizeof(QueueNode));
if(head == NULL)
{
printf("malloc failed\n");
return;
} head->next = NULL;
queue->front = queue->rear = head; return;
} void insertLinkQueue(LinkQueue *queue, QueueElemType data)
{
QueueNode *newNode = (QueueNode *)malloc(sizeof(QueueNode));
if(NULL == newNode)
{
printf("malloc failed\n");
return;
} newNode->data = data;
newNode->next = NULL; queue->rear->next = newNode;
queue->rear = newNode; return;
} int deleteLinkQueue(LinkQueue *queue, QueueElemType *data)
{
QueueNode *p; if (queue->front == queue->rear)
{
printf("no element!\n");
return 0;
} p = queue->front->next;
*data = p->data; queue->front->next = p->next;
if (p == queue->rear)
{
queue->rear = queue->front;
} free(p);
return 1;
}
void CreateALGraph(Graph *G)
{
int i, j, k;
int c; printf("输入顶点数和边数:\n");
scanf("%d %d", &G->vexNum, &G->edgeNum);
setbuf(stdin, NULL); for (i = 0; i < G->vexNum; i++)
{
printf("输入第%d个顶点信息:\n", i + 1);
scanf("%c", &G->vexs[i]); while((c = getchar()) != '\n' && c != EOF);
} for (i = 0; i < G->vexNum; i++)
{
for (j = 0; j < G->vexNum; j++)
{
G->arc[i][j] = 0;
}
} for (k = 0; k < G->edgeNum; k++)
{
printf("输入边(vi,vj)的下标i,j:\n");
scanf("%d %d", &i, &j); while((c = getchar()) != '\n' && c != EOF); // set a default weight
G->arc[i][j] = G->arc[j][i] = 1;
}
} void BFSTraverse(Graph G)
{
LinkQueue queue;
QueueElemType q; initLinkQueue(&queue); for(int i = 0; i < G.vexNum; i++)
{
if (!visit[i])
{
visit[i] = 1;
printf("%c ", G.vexs[i]); insertLinkQueue(&queue, i);
while (deleteLinkQueue(&queue, &q))
{
for (int j = 0; j < G.vexNum; j++)
{
if (G.arc[q][j] == 1 && !visit[j])
{
visit[j] = 1;
printf("%c ", G.vexs[j]);
insertLinkQueue(&queue, j);
}
}
}
}
}
} int main(int argc, char const *argv[])
{
Graph G;
CreateALGraph(&G); BFSTraverse(G);
return 0;
}

运行结果:A B F C G I E D H

图算法之BFS的更多相关文章

  1. 图算法(一)——基本图算法(BFS,DFS及其应用)(1)

    1)BFS 广度优先搜索:给定源节点s,生成广度优先搜索树广度优先搜索树中从节点s到节点v的简单路径对应的就是s到v的最短路径(边数最少的路径)广度优先:将已发现节点与未发现节点之间的边界(灰色节点) ...

  2. 经典图算法Java代码实践:BFS,DFS以及几种最短路径算法

    public class City { String name; int id; static int idCounter = 0; public City(String name) { this.n ...

  3. 程序员的算法课(18)-常用的图算法:广度优先(BFS)

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/m0_37609579/article/de ...

  4. 图算法(一)——基本图算法(BFS,DFS及其应用)(2)

    2)DFS 深度优先搜索总是对最近发现的节点v的出发边进行搜索,直到该节点的所有出发边都被发现 一旦节点v的所有出发边都被发现,搜索回溯到v的前驱结点进行 实现细节:时间戳 每一个结点有一个发现时间和 ...

  5. 算法系列之图--BFS

    广度优先搜索以源结点s为出发点,算法始终将已发现和未发现结点之间的边界,沿其广度方向向外扩展.也即算法需要在发现所有距离源结点s为k的所有结点之后才会去发现距离源结点距离为k+1的其他结点. talk ...

  6. 图的 储存 深度优先(DFS)广度优先(BFS)遍历

    图遍历的概念: 从图中某顶点出发访遍图中每个顶点,且每个顶点仅访问一次,此过程称为图的遍历(Traversing Graph).图的遍历算法是求解图的连通性问题.拓扑排序和求关键路径等算法的基础.图的 ...

  7. 【Python算法】遍历(Traversal)、深度优先(DFS)、广度优先(BFS)

    图结构: 非常强大的结构化思维(或数学)模型.如果您能用图的处理方式来规范化某个问题,即使这个问题本身看上去并不像个图问题,也能使您离解决问题更进一步. 在众多图算法中,我们常会用到一种非常实用的思维 ...

  8. 大数据技术之_19_Spark学习_05_Spark GraphX 应用解析 + Spark GraphX 概述、解析 + 计算模式 + Pregel API + 图算法参考代码 + PageRank 实例

    第1章 Spark GraphX 概述1.1 什么是 Spark GraphX1.2 弹性分布式属性图1.3 运行图计算程序第2章 Spark GraphX 解析2.1 存储模式2.1.1 图存储模式 ...

  9. 判断图连通的三种方法——dfs,bfs,并查集

    Description 如果无向图G每对顶点v和w都有从v到w的路径,那么称无向图G是连通的.现在给定一张无向图,判断它是否是连通的. Input 第一行有2个整数n和m(0 < n,m < ...

  10. Day1 BFS算法的学习和训练

    ​ 因为自己的原因,之前没有坚持做算法的相应学习,总是觉得太难就半途而废,真的算是一个遗憾了,所以现在开始,定一个30天入门学习算法计划. ​ 我是根据<算法图解>的顺序进行安排的,自己对 ...

随机推荐

  1. tp insertAll与saveAll

    在批量插入数据时 insertAll是Db类的,而saveAll是基于模型的

  2. 【读书笔记】Linux系统管理初学者指南读书笔记1——第1-2章

    本博客记录一下<Linux系统管理初学者指南>这本书的读书笔记,最近由于想做一些关于嵌入式的项目,所以需要对Linux系统进行学习,正好之前买过这本书,内容还可以,能作为入门阅读 第1章 ...

  3. Java方法之方法的重载

    方法的重载 重载就是在一个类中,有相同的函数名称,但形参不同的函数. 方法的重载的规则: 1.方法名称必须相同. 2.参数列表必须不同(个数不同.或类型不同.参数排列顺序不同等). 3.方法的返回类型 ...

  4. linux离线安装gcc 和g++

    1.先到有网的机器上下载依赖包 sudo yum install --downloadonly --downloaddir=/home/mjb/soft/gcc gcc sudo yum instal ...

  5. mysql增删改查json中的某个字段

    创建表 1 CREATE TABLE t_json(id INT PRIMARY KEY, NAME VARCHAR(20), info JSON); 插入记录 1 INSERT INTO t_jso ...

  6. ubuntu22.04安装mysql5.7

    22版本的ubuntu默认安装mysql8.0版本,要想安装5.x的版本就得下载安装,这个比较详细的教程,可以参考: https://www.cnblogs.com/juanxincai/p/1648 ...

  7. kubernetes中 pause的作用

    pause的作用 重要概念:Pod内的容器都是平等的关系,共享Network Namespace.共享文件 pause容器的最主要的作用:创建共享的网络名称空间,以便于其它容器以平等的关系加入此网络名 ...

  8. JMeter基础 — JMeter聚合报告详解

    提示:聚合报告组件的使用和察看结果树组件的使用方式相同.本篇文章主要是详细的介绍一下聚合报告组件内容,不做示例演示. 1.聚合报告介绍 在使用JMeter进行性能测试时,聚合报告(Aggregate ...

  9. python菜鸟学习: 3.浅copy使用场景

    # -*- coding: utf-8 -*-import copy# 浅copy# 使用场景,比如A,B夫妻共有一个银行账户,存取马宁的数据username = ["name", ...

  10. 多线程—ThreadLocal

    一.ThreadLocal的含义 线程的变量副本(就像命名一样),每个线程隔离. 二.ThreadLocal的结构 每个Thread都有自己的ThreadLocalMap,ThreadLocalMap ...