重新教自己学算法之图的遍历(十一)—深度(DFS)和广度(BFS)
来源:互联网 发布:人工智能分析用户行为 编辑:程序博客网 时间:2024/05/22 13:05
好几天没有补算法了。以前对于图的各种算法没有学好,特此机会重新复习一下图的基本算法。
图的定义:
图是一种数据结构,和树一样可以用二元组表示。它可定义为Graph=(V,R)其中,V={x|x∈datatype},R={VR},VR={(x,y)|P(x,y)∧(x,y∈V)}, V是顶点的非空有穷集合,R是边的有穷集合。
也就是说说,图就是记录一些点和点之间的关系的数据结构。
图的存储:
1:邻接矩阵:一个二维数组,不同下标对应着不同的点。分为无向图和有向图。如果是无向图,vi<->vj 即 graph[vi][vj] = graph[vj][vi] = 1; 有向图 vi->vj 则只有graph[vi][vj] = 1。如果边上有权重val,则graph[vi][vj] = val。
而虽然邻接矩阵在记录边关系时很方便,但是面临的问题是浪费大量空间,特别是面对稀疏图(即图中边的数量大大少于节点数量)时,问题尤其明显。因为我们的示例图很简单,所以接下来我用的都是邻接矩阵。
2:邻接表:
邻接表的出现解决了邻接矩阵的问题,即使用了链式结构。 邻接表的处理方法是这样的:
(1):图中顶点用一个一维数组存储。
(2):图中每个顶点vi的所有邻接点构成一个线性表,由于邻接点的个数不定,所以,用链表存储。链表中每个节点有两个信息:当前顶点的下标,指向下一节点的指针。在该图中,数组里面的下标对应不同的顶点,而链表里的节点对应这个顶点的邻接点。
图的遍历:
1:深度优先搜索(DFS):注重的是深度优先。
拿上图举例,我们从v1出发,如果我们先走左边的顶点(这个左边在程序里即第一个顶点),我们走到了v2,发现还能往下(下的意思是有邻接点存在)走,走左边到了v4,发现有岔路口,但是v1我们走过了,只能走v5,v5走到了v3。此时全部点都遍历了一遍,即DFS完成。顺序:v1,v2,v4,v5,v3。
2:广度优先搜索(BFS):注重广度,按层次遍历。
即先把眼前的地方先走一遍,再接着遍历更远的地方。拿上图举例。我们从v1出发,首先把眼前的顶点遍历完(即遍历v1所有的邻接点),我们遍历了v2,v3,v4。然后从最左边的顶点接着重复此过程,遍历了v5。此时全部点都遍历了一遍,即BFS完成。顺序:v1,v2,v3,v4,v5。
了解基本思想,仔细阅读源代码,并动手运算一遍。
//本实例通过建立邻接矩阵来遍历图#include <iostream>#include <cstdlib>#include <cassert>#include <cstring>#include <queue>using namespace std;#define MAX 100#define max(x,y)(x > y ? x : y)//这里假设我们从顶点1开始遍历#define initNode 1typedef struct{ int matrix[MAX][MAX]; int num;}Graph;Graph example;void createPoint(){ int i, j; //图的初始化 memset(example.matrix, 0 ,sizeof(example.matrix)); example.num = 0; while(cin>>i>>j && i != 0 && j != 0) { example.matrix[i][j] = 1; example.matrix[j][i] = 1; //出现的最大数即为最大顶点数 example.num = max(example.num, i); example.num = max(example.num, j); }}void DFS(int x, int* visited){ cout<<" "<<x; for(int i = 1; i <= example.num; i++) { if (visited[i] == 0 && example.matrix[x][i] == 1) { visited[i] = 1; DFS(i, visited); } }}void BFS(){ int i, nNode; queue<int> gQueue; int* visited = new int[example.num++]; memset(visited, 0, sizeof(int)*(example.num++));//此处的*为乘号 cout<<"BFS"<<"------------------"<<endl; visited[initNode] = 1; gQueue.push(initNode); while(!gQueue.empty()) { nNode = gQueue.front(); cout<<" "<<nNode; for (int i = 1; i <= example.num; ++i) { if(example.matrix[nNode][i] == 1 && visited[i] == 0) { gQueue.push(i); visited[i] = 1; } } gQueue.pop(); } cout<<endl<<"--------------"<<endl;}void initDFS(){ int* visited = new int[example.num++]; memset(visited, 0, sizeof(int)*(example.num++)); cout<<"DFS"<<"----------------"<<endl; visited[initNode] = 1; DFS(initNode,visited); cout<<endl<<"DFS"<<"----------------"<<endl;}void test(){ createPoint(); cout<<example.num<<endl; BFS(); initDFS();}int main(int argc, char const *argv[]){ test(); return 0;}
参考文章:http://blog.csdn.net/u010006643/article/details/45673571
- 重新教自己学算法之图的遍历(十一)—深度(DFS)和广度(BFS)
- 图的遍历(搜索)算法(深度优先算法DFS和广度优先算法BFS)
- 图的遍历(搜索)算法(深度优先算法DFS和广度优先算法BFS)
- 重新教自己学算法之开篇(一)
- 重新教自己学算法之循环-递归(二)
- 重新教自己学算法之线性队列(七)
- 重新教自己学算法之线性堆栈(八)
- 重新教自己学算法之图的最短路(十二)
- 图的遍历记(深度和广度优先搜索—BFS&&DFS)的笔记
- 重新教自己学算法之非递归排序——冒泡-插入-排序(三)
- 重新教自己学算法之递归排序——快速排序(四)
- 重新教自己学算法之递归排序——合并排序(五)
- 重新教自己学算法之递归排序——堆排序(六)
- 图的深度优先遍历(DFS)和广度优先遍历(BFS)--解析
- 图的深度优先遍历(DFS)和广度优先遍历(BFS)
- 重新教自己学算法之单词统计(状态机)(十)
- 重新教自己学算法之单向链表(九)
- DOM中BFS(广度优先遍历)和DFS(深度优先遍历)的方法
- C++实现反射机制(二)
- Android Bitmap回收 注意事项
- Android应用AsyncTask处理机制详解及源码分析
- 路由器安全测试工具 – Router Scan v2.51
- 为程序界面添加滑动条--createTrackbar()
- 重新教自己学算法之图的遍历(十一)—深度(DFS)和广度(BFS)
- 强连通分量分解
- java中的IO流(2)----读取文本数据
- leetcode Merge Two Sorted Lists
- R 在使用 .csv檔 的一般問題
- leetcode 之 Reverse Linked List
- ios日期格式转换
- fatal error: Python.h: No such file or directory 解决办法
- Data API