图的基础算法-广度优先搜索/深度优先搜索
2016-01-22 17:25
218 查看
图有矩阵存储和链表存储两种。这里采用链表存储。
参考《算法导论》上面的做法,首先定义图结点的结构。为了跟踪算法的进展,广度优先搜索在概念上将每个结点涂成白色。在算法推进过程中,结点的颜色可能变成灰色或者黑色。在搜索过程中,第一次遇到一个结点时,表示该结点已被发现,此时该结点的颜色将从白色变成灰色。灰色或黑色结点都是已经被发现过的结点。所有与黑色结点邻接的结点都已经被发现。对于灰色结点来说,其邻接结点中可能存在未被发现的白色结点。
BFS
在执行广度优先搜索的过程中将构造出一棵广度优先树。一开始树中只有根结点s,在扫描已发现结点u的邻接链表时,每当发现一个白色结点v,就将白色结点v和边(u,v)同时加入该树里面。在广度优先树中,u是v的父结点。
首先选定源结点s作为根结点,从源结点开始遍历。利用队列来管理灰色结点。
广度优先搜索能够正确计算出最短路径距离
DFS
深度优先搜索总是对最近才发现的结点v的出发边进行探索,直到该结点所有出发边都被发现为止。一旦结点v的所有出发边都被发现为止。一旦结点的所有出发边都被发现,搜索则“回溯”到v的前驱结点(v是经过该结点才被发现的),来搜索该前驱结点的出发边。该过程一直持续到从源结点可以到达的所有结点都被发现为止。
代码的实现细节是针对笔者实现的图的类的相关接口来编写的。所以读者可能看不太懂代码,可以留言向笔者索要源代码,欢迎大家交流讨论。
参考《算法导论》上面的做法,首先定义图结点的结构。为了跟踪算法的进展,广度优先搜索在概念上将每个结点涂成白色。在算法推进过程中,结点的颜色可能变成灰色或者黑色。在搜索过程中,第一次遇到一个结点时,表示该结点已被发现,此时该结点的颜色将从白色变成灰色。灰色或黑色结点都是已经被发现过的结点。所有与黑色结点邻接的结点都已经被发现。对于灰色结点来说,其邻接结点中可能存在未被发现的白色结点。
struct graphNode { int ver; //为结点定义颜色,方便在遍历树的时候,标记结点是否已经访问。 //white表示还没有访问过的结点 //gray表示已经访问过的结点(结点一旦被访问,就设置color为“gray”) //black表示该节点的邻接结点都已访问过,由gray变成black string color; //遍历过程中记录该结点的父结点 graphNode* peer; //遍历过程记录该结点的深度 int dest; //stime是遍历该结点的起始时间,ftime该结点的邻接结点遍历完成回到该结点的时间(用于深度优先搜索) int stime; int ftime; graphNode() { color = "white"; peer = NULL; dest = 0; stime = 0; ftime = 0; } graphNode(int v):ver(v) { color = "white"; peer = NULL; dest = 0; stime = 0; ftime = 0; } graphNode(graphNode &g) { ver = g.ver; color = g.color; peer = g.peer; dest = g.dest; stime = g.stime; ftime = g.ftime; } };
BFS
在执行广度优先搜索的过程中将构造出一棵广度优先树。一开始树中只有根结点s,在扫描已发现结点u的邻接链表时,每当发现一个白色结点v,就将白色结点v和边(u,v)同时加入该树里面。在广度优先树中,u是v的父结点。
首先选定源结点s作为根结点,从源结点开始遍历。利用队列来管理灰色结点。
广度优先搜索能够正确计算出最短路径距离
void BFSearch(linkedgraph &g, int v) { arrayQueue<graphNode*> q; graphNode *s = &g.gnode[v-1]; s->color = "gray"; //将源结点插入队列 q.push(s); while (q.empty() == false) { graphNode *u = q.front(); int size = g.gchain[u->ver - 1].size(); //遍历队列首项的结点的邻接链表中所有的结点 for (int i = 1; i <= size; i++) { graphNode *v = g.gchain[u->ver - 1].get(i); if (v->color == "white") { v->color = "gray"; v->peer = u; v->dest = u->dest + 1; cout << v->ver << endl; q.push(v); } } //遍历完该结点的邻接结点后,将该结点的color改为“black”,然后删除队列中该结点 u->color = "black"; q.pop(); } return; }
DFS
深度优先搜索总是对最近才发现的结点v的出发边进行探索,直到该结点所有出发边都被发现为止。一旦结点v的所有出发边都被发现为止。一旦结点的所有出发边都被发现,搜索则“回溯”到v的前驱结点(v是经过该结点才被发现的),来搜索该前驱结点的出发边。该过程一直持续到从源结点可以到达的所有结点都被发现为止。
void DFSvisit(linkedgraph &g, graphNode* s,int &time) { time++; s->color = "gray"; s->stime = time; int size = g.gchain[s->ver - 1].size(); for (int i = 1; i <= size; i++) { graphNode* v = g.gchain[s->ver - 1].get(i); if (v->color == "white") { v->peer=u; //递归遍历 DFSvisit(g, v, time); } } s->color = "black"; time++; s->ftime = time; cout << s->stime << " " << s->ftime << endl; return; } void DFSearch(linkedgraph &g, int v) { graphNode* s = &g.gnode[v - 1]; int time = 0; DFSvisit(g, s,time); return; }
代码的实现细节是针对笔者实现的图的类的相关接口来编写的。所以读者可能看不太懂代码,可以留言向笔者索要源代码,欢迎大家交流讨论。
相关文章推荐
- Win2003利用dfs(分布式文件系统)在负载均衡下的文件同步配置方案
- win2003分布式文件系统(dfs)配置方法[图文详解]
- win2003分布式文件系统及其部署 图文教程
- Hadoop2.6+jdk8的安装部署(1)——使用jar包安装部署【详细】
- Hadoop FS Shell
- DFS使用方法总结
- FastDFS注意事项
- 无忧技术带您预览DFS(分布式文件系统)管理控制台
- C 语言实现迷宫 DFS算法
- 一幅图弄清DFT与DTFT,DFS的关系
- HDFS---Namenode
- HDFS ---- Services startup
- POJ1523 SPF dfs
- poj1731 Orders dfs
- Surrounded Regions
- Word Ladder, Gray Code
- Binary Tree Zigzag Level Order Traversal,Restore IP Addresses,Word Search,Simplify Path
- UVA 11624
- HDU1495
- DFS求岛的个数LeetCode 200. Number of Islands