图的遍历-深搜(DFS)和广搜(BFS)
2015-05-12 19:07
302 查看
最近为了保研在复习数据结构和算法,想来可以用博客记录一些,以后或许能用的上。
首先说一下图的定义。
图是一种数据结构,图和树一样可以用二元组表示。它可定义为Graph=(V,R)其中,V={x|x∈datatype},R={VR},VR={(x,y)|P(x,y)∧(x,y∈V)}。在图中,数据元素常称为顶点(Vertex),V是顶点的非空有穷集合;R是边(弧)的有穷集合。
也就是说,图就是记录一些点和点之间的关系的数据结构。
图的存储大致分为两类,因为主要想说的是遍历,所以大概说一下存储。
邻接矩阵
邻接矩阵就是一个二维数组,不同的下标对应着不同的结点。而如果是无向图,vi<->vj 即 graph[vi][vj] = graph[vj][vi] = 1; 有向图 vi->vj 则只有graph[vi][vj] = 1。如果边上有权重val,则graph[vi][vj] = val。
而虽然邻接矩阵在记录边关系时很方便,但是面临的问题是浪费大量空间,特别是面对稀疏图(即图中边的数量大大少于节点数量)时,问题尤其明显。因为我们的示例图很简单,所以接下来我用的都是邻接矩阵。
邻接表
邻接表的出现解决了邻接矩阵的问题,即使用了链式结构。 邻接表的处理方法是这样的:
图中顶点用一个一维数组存储。
图中每个顶点vi的所有邻接点构成一个线性表,由于邻接点的个数不定,所以,用链表存储。链表中每个节点有两个信息:当前顶点的下标,指向下一节点的指针。在该图中,数组里面的下标对应不同的顶点,而链表里的节点对应这个顶点的邻接点。
接下来是本文的主要点:图的遍历。
上面是一个无向图的示例图。
深度优先搜索(DFS)
由这个名字我们就能知道,DFS注重的是深度优先。即走一条路走到底,走不动了回来看有没有岔路口,有的话接着走到底。当然已经走过的地方不能再走一遍了。拿上图举例,我们从v1出发,如果我们先走左边的顶点(这个左边在程序里即第一个顶点),我们走到了v2,发现还能往下(下的意思是有邻接点存在)走,走左边到了v4,发现有岔路口,但是v1我们走过了,只能走v5,v5走到了v3。此时全部点都遍历了一遍,即DFS完成。顺序:v1,v2,v4,v5,v3。
广度优先搜索(BFS)
BFS注重的是广度,按层次遍历。即先把眼前的地方先走一遍,再接着遍历更远的地方。拿上图举例。我们从v1出发,首先把眼前的顶点遍历完(即遍历v1所有的邻接点),我们遍历了v2,v3,v4。然后从最左边的顶点接着重复此过程,遍历了v5。此时全部点都遍历了一遍,即BFS完成。顺序:v1,v2,v3,v4,v5。
我们可以看出来,BFS和DFS的时间复杂度相同,不同的只有遍历顶点的顺序不同而已。所以我们根据不同的情况使用不同的遍历方法即可。
下面是创建邻接矩阵图,DFS和BFS的代码:
输出结果(输入的形式是以邻接点对的形式,以0 0结束):
首先说一下图的定义。
图是一种数据结构,图和树一样可以用二元组表示。它可定义为Graph=(V,R)其中,V={x|x∈datatype},R={VR},VR={(x,y)|P(x,y)∧(x,y∈V)}。在图中,数据元素常称为顶点(Vertex),V是顶点的非空有穷集合;R是边(弧)的有穷集合。
也就是说,图就是记录一些点和点之间的关系的数据结构。
图的存储大致分为两类,因为主要想说的是遍历,所以大概说一下存储。
邻接矩阵
邻接矩阵就是一个二维数组,不同的下标对应着不同的结点。而如果是无向图,vi<->vj 即 graph[vi][vj] = graph[vj][vi] = 1; 有向图 vi->vj 则只有graph[vi][vj] = 1。如果边上有权重val,则graph[vi][vj] = val。
而虽然邻接矩阵在记录边关系时很方便,但是面临的问题是浪费大量空间,特别是面对稀疏图(即图中边的数量大大少于节点数量)时,问题尤其明显。因为我们的示例图很简单,所以接下来我用的都是邻接矩阵。
邻接表
邻接表的出现解决了邻接矩阵的问题,即使用了链式结构。 邻接表的处理方法是这样的:
图中顶点用一个一维数组存储。
图中每个顶点vi的所有邻接点构成一个线性表,由于邻接点的个数不定,所以,用链表存储。链表中每个节点有两个信息:当前顶点的下标,指向下一节点的指针。在该图中,数组里面的下标对应不同的顶点,而链表里的节点对应这个顶点的邻接点。
接下来是本文的主要点:图的遍历。
上面是一个无向图的示例图。
深度优先搜索(DFS)
由这个名字我们就能知道,DFS注重的是深度优先。即走一条路走到底,走不动了回来看有没有岔路口,有的话接着走到底。当然已经走过的地方不能再走一遍了。拿上图举例,我们从v1出发,如果我们先走左边的顶点(这个左边在程序里即第一个顶点),我们走到了v2,发现还能往下(下的意思是有邻接点存在)走,走左边到了v4,发现有岔路口,但是v1我们走过了,只能走v5,v5走到了v3。此时全部点都遍历了一遍,即DFS完成。顺序:v1,v2,v4,v5,v3。
广度优先搜索(BFS)
BFS注重的是广度,按层次遍历。即先把眼前的地方先走一遍,再接着遍历更远的地方。拿上图举例。我们从v1出发,首先把眼前的顶点遍历完(即遍历v1所有的邻接点),我们遍历了v2,v3,v4。然后从最左边的顶点接着重复此过程,遍历了v5。此时全部点都遍历了一遍,即BFS完成。顺序:v1,v2,v3,v4,v5。
我们可以看出来,BFS和DFS的时间复杂度相同,不同的只有遍历顶点的顺序不同而已。所以我们根据不同的情况使用不同的遍历方法即可。
下面是创建邻接矩阵图,DFS和BFS的代码:
#include<iostream> #include<string.h> #include<queue> using namespace std; #define MAX 100 #define max(x,y)(x>y?x:y) #define initNode 1 //这里我们假设遍历从顶点1开始,也可以改成其他的 typedef 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); } } // DFS 函数主体 用递归实现 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); } } } // DFS DFS初始化 void initDFS(){ int *visited = new int[example.num++]; memset(visited,0,sizeof(int)*(example.num+1)); cout<<"DFS"<<"------------------------------------"<<endl; visited[initNode]=1; DFS(initNode,visited); cout<<endl<<"DFS"<<"------------------------------------"<<endl; } // BFS 用队列实现该功能 void BFS(){ int i,nNode; queue<int> gQueue; int *visited = new int[example.num++]; memset(visited,0,sizeof(int)*(example.num+1)); cout<<"BFS"<<"------------------------------------"<<endl; visited[initNode]=1; gQueue.push(initNode); while(!gQueue.empty()){ nNode = gQueue.front(); cout<<" "<<nNode; for(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<<"BFS"<<"------------------------------------"<<endl; } int main(){ createPoint(); BFS(); initDFS(); return 0; }
输出结果(输入的形式是以邻接点对的形式,以0 0结束):
1 2 1 4 1 3 2 4 2 5 3 5 4 5 0 0 BFS------------------------------------ 1 2 3 4 5 BFS------------------------------------ DFS------------------------------------ 1 2 4 5 3 DFS------------------------------------
相关文章推荐
- 图的遍历--使用邻接表作为存储结构的遍历(DFS、BFS)C语言
- 广度优先遍历-BFS、深度优先遍历-DFS
- bfs,dfs遍历图的模板
- 图(邻接表)的遍历——DFS(深度优先搜索)和BFS(广度优先搜索)和连通图
- 利用邻接矩阵存储无向图,并实现BFS(非递归) DFS(递归+非递归)两种遍历
- HDU 4707 Pet 图的遍历(BFS和DFS)
- 图的遍历:DFS BFS
- 邻接矩阵 遍历 DFS And BFS~~~
- 图的深度优先遍历DFS和广度优先遍历BFS
- 图的遍历 DFS(深度优先),BFS(广度优先)
- 图的遍历:DFS和BFS
- 算法导论—无向图的遍历(BFS+DFS,MATLAB)
- DFS,BFS,前序,中序,后序,层序遍历
- Java数据结构----图--深度优先遍历BFS和广度优先遍历DFS
- 图的遍历(DFS与BFS)
- 图的遍历(dfs、bfs、最短路、最小生成树、拓扑排序)
- hdu 4771 求一点遍历全部给定点的最短路(bfs+dfs)
- 图的遍历算法DFS和BFS(C++)
- 图遍历算法——DFS、BFS、A*、B*和Flood Fill 遍历算法大串讲
- 数据结构 学习笔记(七):图(上):图的表示方法(邻接表,邻接矩阵),遍历(DFS,BFS)