一、深度优先搜索(Depth-First-Search 简称:DFS)

1.1 遍历过程:

  (1)从图中某个顶点v出发,访问v。

  (2)找出刚才第一个被顶点访问的邻接点。访问该顶点。以这个顶点为新的顶点,重复此步骤,直到访问过的顶点没有未被访问过的顶点为止。

  (3)返回到步骤(2)中的被顶点v访问的,且还没被访问的邻接点,找出该点的下一个未被访问的邻接点,访问该顶点。

  (4)重复(2) (3) 直到每个点都被访问过,遍历结束。

例无权图:(默认为字母顺序)

  (1)从顶点A出发,访问该图

  (2)A的邻接点为BEF 以B为顶点开始访问 B的邻接点有FDC

  (3)B的所有的点均被访问结束,访问顶点C 顶点C还有F没有被访问

,结束遍历。

故遍历结果为 A->B->C->D->E->F

有向图:(默认为字母顺序)

  (1)从顶点A出发,访问该图

  (2)A 的出路顶点为B、D ,从顶点B 开始访问, B的出路只有E 结束此路;

  (3)开始访问顶点D,D的出路为顶点C和F 此时所有顶点都被遍历了,结束;

故遍历结果为: A->B->E->D->C->F

1.2 算法描述

自然语言:从图中的某个顶点v出发,访问v,并将visited[v]的值为true。

      一次检查v的所有邻接点w,如果visited[w]的值为flase,再从w出发进行递归遍历,直到图中的所有顶点都被访问过。

伪代码:

递归算法:

  visited[MVNum] <-- false

  count<--v,visited[v]<--true;

  for(w<--FirstAdjVex(G,v);w>=0;w<--NextAdjVex(G,v,w))

    if(!visited[w]  DFS[G,w]);

采用邻接矩阵表示:

//输入图G(V,E),w表示v的邻接点

//输出邻接矩阵

count<--v; visited[v]<--true;

for(w<--0;w<G.vexnum;w++)

  if( (G.arcs[v][w]!=0)&&(!visited[w])  )

    DFS(G,w);

采用邻接表:

count<--v; visited[v]<--true;

p<--G.vertices[v].firstarc;

while(p!=NULL) do

  w<--p->adjvex;

  if(!visited[w]) do DFS(G,w)

  p<-- p->nextarc;

1.3用途:检查图的连通性和无环性

1.4总结:每个顶点至多进一次队列。遍历图的过程实质上市通过边找邻接点的过程。因此DFS时间复杂度,当用邻接矩阵表示图时为O(n2),其中n为图中的顶点数,当以邻接表做图的存储结构时,时间复杂度为O(e)这里e为 图中的边数,因此,当以邻接表为存储结构时,DFS时间复杂度为O(n+e)。

二、广度优先搜索(Breadth-First-Search 简称:BFS)

2.1遍历过程如下:

  (1)从图中某个顶点v出发,访问v。

  (2)依次访问v邻接各个未访问过的的所有顶点

  (3)接着从这些邻接顶点中继续访问它们的邻接顶点,遵循原则 先被访问的顶点的邻接点   先于 后被访问的顶点的邻接点 被访问。重复(3)步骤,直至所有的顶点都被访问过。

这里的“先被访问的顶点的邻接点 ”指的是在第二步骤先访问的顶点然后再先访问他的邻接点,包括后来的第三步骤也是这个意思,均为上一步骤 先访问的顶点然后再先访问他的邻接点。

例:图还是上面的那张无权图

我们按照字母ABCDEF这样的顺序来排列

(1)以A为顶点,开始遍历

(2)A的三个邻接点BEF

(3)根据字母顺序 从点B开始访问 B的临界点有CD 此时,所有的顶点均被访问

故,遍历后的结果为 A ->B-> E-> F-> C-> D

若为有向图

(1)根据字母顺序,先从顶点A开始访问

(2)看顶点A的出路,邻接点为B,D 。根据字母顺序,下一个顶点从B开始

(3)顶点B的出路为E ,且E没有出路了,故此路结束

(4)回到和B点同一级的 还有顶点D还没有被访问 D的出路有两条,分别为邻接点C 和F ,此时所有的顶点都被访问过。

故 遍历后的顺序为 A->B->D->E->C->F

2.2算法描述

自然语言:从图 中的某个顶点v出发,访问v,并将visited[v]的值为true,然后将v进队

     只要队列不空,则重复下述处理:

      队头顶点u出队

      依次检查u的所有邻接点w,如果visited[w]的值为false,则访问w,并将visited[w]的数值为true,然后将w入队;

伪代码: //BFS算法描述

    //输入:图G=<V,E>

    //输出:图G的BFS遍历后的先后次序

    visited[v] <--true

    InitQueue(Q);

    EnQueue(Q,v);

    while(!QueueEmpty(Q))  do

      DeQueue(Q,u);

      for(w <--FirstAdjVex(G,u);w>=0;w<--NextAdjVex(G,u,w))

      if(!visited[w]) do

        count<<w; visited[w] <--true;

        EnQueue(Q,w);

2.3用途:计算最短路径问题

2.4.总结:每个顶点至多进一次队列。遍历图的过程实质上市通过边找邻接点的过程。因此BFS时间复杂度,当用邻接矩阵表示图时为O(n2),其中n为图中的顶点数,当以邻接表做图的存储结构时,时间复杂度为O(e)这里e为 图中的边数,因此,当以邻接表为存储结构时,BFS时间复杂度为O(n+e)。

具体的代码实现如下所示:

#include<stdio.h>
#define N 20
#define TRUE 1
#define FALSE 0
int visited[N]; /*访问标志数组*/
typedef struct /*队列的定义*/
{
int data[N];
int front,rear;
}queue; typedef struct /*图的邻接矩阵*/
{
int vexnum,arcnum;
char vexs[N];
int arcs[N][N];
}
graph; void createGraph(graph *g); /*建立一个无向图的邻接矩阵*/
void dfs(int i,graph *g); /*从第i个顶点出发深度优先搜索*/
void tdfs(graph *g); /*深度优先搜索整个图*/
void bfs(int k,graph *g); /*从第k个顶点广度优先搜索*/
void tbfs(graph *g); /*广度优先搜索整个图*/
void init_visit(); /*初始化访问标识数组*/ /*建立一个无向图的邻接矩阵*/
void createGraph(graph *g)
{
int i,j;
char v;
g->vexnum=;
g->arcnum=;
i=;
printf("\n输入顶点序列(以#结束):\n");
while ((v=getchar())!='#')
{
g->vexs[i]=v; /*读入顶点信息*/
i++;
}
g->vexnum=i; /*顶点数目*/
for (i=;i<g->vexnum;i++) /*邻接矩阵初始化*/
for (j=;j<g->vexnum;j++)
g->arcs[i][j] = ;/*(1)-邻接矩阵元素初始化为0*/
printf("\n输入边的信息(顶点序号,顶点序号),以(-1,-1)结束:\n");
scanf("%d,%d",&i,&j); /*读入边(i,j)*/
while (i!=-) /*读入i为-1时结束*/
{
g->arcs[i][j] = ; /*(2)-i,j对应边等于1*/
g->arcnum++;
scanf("%d,%d",&i,&j);
}
}/* createGraph */ /*(3)---从第i个顶点出发深度优先搜索,补充完整算法*/
void dfs(int i,graph *g)
{
int j;
printf("%c", g->vexs[i]);
visited[i] = TRUE;
for (j = ; j < g->vexnum; j++)
if (g->arcs[i][j] == && !visited[j])
dfs(j, g);
}/* dfs */ /*深度优先搜索整个图*/
void tdfs(graph *g)
{
int i;
printf("\n从顶点%C开始深度优先搜索序列:",g->vexs[]);
for (i=;i<g->vexnum;i++)
if (visited[i] != TRUE) /*(4)---对尚未访问过的顶点进行深度优先搜索*/
dfs(i,g);
printf("\n");
}/*tdfs*/ /*从第k个顶点广度优先搜索*/
void bfs(int k,graph *g)
{
int i,j;
queue qlist,*q;
q=&qlist;
q->rear=;
q->front=;
printf("%c",g->vexs[k]);
visited[k]=TRUE;
q->data[q->rear]=k;
q->rear=(q->rear+)%N;
while (q->rear!=q->front) /*当队列不为空,进行搜索*/
{
i=q->data[q->front];
q->front=(q->front+)%N;
for (j=;j<g->vexnum;j++)
if ((g->arcs[i][j]==)&&(!visited[j]))
{
printf("%c",g->vexs[j]);
visited[j]=TRUE;
q->data[q->rear] = j; /*(5)---刚访问过的结点入队*/
q->rear = (q->rear + ) % N; /*(6)---修改队尾指针*/
}
}
}/*bfs*/ /*广度优先搜索整个图*/
void tbfs(graph *g)
{
int i;
printf("\n从顶点%C开始广度优先搜索序列:",g->vexs[]);
for (i=;i<g->vexnum;i++)
if (visited[i]!=TRUE)
bfs(i,g); /*从顶点i开始广度优先搜索*/
printf("\n");
}/*tbfs*/ void init_visit() /*初始化访问标识数组*/
{
int i;
for (i=;i<N;i++)
visited[i]=FALSE;
} int main()
{
graph ga;
int i,j;
printf("***********图邻接矩阵存储和图的遍历***********\n");
printf("\n1-输入图的基本信息:\n");
createGraph(&ga);
printf("\n2-无向图的邻接矩阵:\n");
for (i=;i<ga.vexnum;i++)
{
for (j=;j<ga.vexnum;j++)
printf("%3d",ga.arcs[i][j]);
printf("\n");
}
printf("\n3-图的遍历:\n");
init_visit(); /*初始化访问数组*/
tdfs(&ga); /*深度优先搜索图*/
init_visit();
tbfs(&ga); /*广度优先搜索图*/
return ;
}

运行结果(输入的为本节中一直用到的无向图)

深度和广度查找不同之处在于对顶点的访问顺序不同。

第一次写博客,应该还是有点问题的(虽然也查了一些资料~.~)

参考资料:

《数据结构(C语言版)》  严蔚敏 李冬梅 吴伟民著 人民邮电出版社

《程序设计中实用的数据结构 》  王建德 吴永辉著  人民邮电出版社

C语言数据结构与算法之深度、广度优先搜索的更多相关文章

  1. python数据结构与算法——图的广度优先和深度优先的算法

    根据维基百科的伪代码实现: 广度优先BFS: 使用队列,集合 标记初始结点已被发现,放入队列 每次循环从队列弹出一个结点 将该节点的所有相连结点放入队列,并标记已被发现 通过队列,将迷宫路口所有的门打 ...

  2. 算法竞赛——BFS广度优先搜索

    BFS 广度优先搜索:一层一层的搜索(类似于树的层次遍历) BFS基本框架 基本步骤: 初始状态(起点)加到队列里 while(队列不为空) 队头弹出 扩展队头元素(邻接节点入队) 最后队为空,结束 ...

  3. Leetcode之深度+广度优先搜索(DFS+BFS)专题-934. 最短的桥(Shortest Bridge)

    Leetcode之广度优先搜索(BFS)专题-934. 最短的桥(Shortest Bridge) BFS入门详解:Leetcode之广度优先搜索(BFS)专题-429. N叉树的层序遍历(N-ary ...

  4. [C语言] 数据结构-衡量算法的标准

    1.衡量算法的标准 算法 解题的方法和步骤 衡量算法的标准 1.时间复杂度 大概程序要执行的次数,而非执行的时间,不同的机器运行时间肯定不一样. 2.空间复杂度 算法执行过程中大概所占用的最大内存 3 ...

  5. c语言数据结构和算法库--cstl---王博--相关网站和博客

    1.官网 http://libcstl.org/download.html 2.下载地址 http://www.pudn.com/downloads171/sourcecode/os/detail79 ...

  6. python数据结构与算法

    最近忙着准备各种笔试的东西,主要看什么数据结构啊,算法啦,balahbalah啊,以前一直就没看过这些,就挑了本简单的<啊哈算法>入门,不过里面的数据结构和算法都是用C语言写的,而自己对p ...

  7. 为什么我要放弃javaScript数据结构与算法(第九章)—— 图

    本章中,将学习另外一种非线性数据结构--图.这是学习的最后一种数据结构,后面将学习排序和搜索算法. 第九章 图 图的相关术语 图是网络结构的抽象模型.图是一组由边连接的节点(或顶点).学习图是重要的, ...

  8. 用python语言讲解数据结构与算法

    写在前面的话:关于数据结构与算法讲解的书籍很多,但是用python语言去实现的不是很多,最近有幸看到一本这样的书籍,由Brad Miller and David Ranum编写的<Problem ...

  9. 数据结构C语言版 弗洛伊德算法实现

    /* 数据结构C语言版 弗洛伊德算法  P191 编译环境:Dev-C++ 4.9.9.2 */ #include <stdio.h>#include <limits.h> # ...

随机推荐

  1. Oracle 检查表的数据变动

    本知识点仅适用于Oracle 9i以上的版本. 查看表的数据变动情况请使用SQL语句:select * from user_tab_modifications; user_tab_modificati ...

  2. Javascript 中 true 和 false

    "" == false // true "0" == false // true "" == "0" //false 以 ...

  3. Java学习---Excel读写操作

    1.1.1. 简介 Apache POI 使用Apache POI 完成Excel读写操作 Apache POI 是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API ...

  4. Connection to linux server with ORACLE SQL DEVELOPER

    1.Link name is random 2.username and password is database account 3.host name  is ip address  ifconf ...

  5. Using shared access signatures (SAS) From Microsoft

    A shared access signature (SAS) provides you with a way to grant limited access to objects in your s ...

  6. December 28th 2016 Week 53rd Wednesday

    Knowledge is a treasure, but practice is the key to it. 知识是珍宝,而实践是获取她的钥匙. I know a lot, but what I r ...

  7. ab 压测工具使用

    转自:http://www.cnblogs.com/lemtree/articles/1676641.html 就是APACHE自带的测试工具AB(apache benchmark).在APACHE的 ...

  8. ZT --- extern "C"用法详解 2010-08-21 19:14:12

    extern "C"用法详解 2010-08-21 19:14:12 分类: C/C++ 1.前言: 时常在cpp的代码之中看到这样的代码: #ifdef __cplusplus ...

  9. iOS自动化-iOS录屏xrecord及解决iPhone设备不显示的问题

    github地址:https://github.com/WPO-Foundation/xrecord 安装方法: git clone https://github.com/WPO-Foundation ...

  10. eclipse 自动生成get/set方法

    Shift+Alt+S 会弹出一个对话框 选择Generate Getters and Setters