深度优先遍历(搜索)(DFS)
来源:互联网 发布:淘宝天猫 编辑:程序博客网 时间:2024/05/22 07:07
深度优先遍历(Depth_First_Search),也称为深度优先搜索,简称DFS。
无向图
无向图对应的邻接矩阵
深度优先遍历其实就是一个递归的过程,像一棵树的前序遍历。它从图中某个顶点v出发,访问此顶点,然后从v的未访问的邻接点出发深度优先遍历图,直至图中所有和v有路径相通的顶点都被访问到。事实上,这里指的是连通图,对于非连通图,只需要对它的连通分量分别进行深度优先遍历,即在先前一个顶点进行一次深度优先遍历后,若图中尚有顶点未被访问则另选图中一个未曾被访问的顶点作起始点,重复上述过程,直到图中所有顶点都被访问到为止。
对以邻接矩阵存储的图进行DFS。如下:
#include<iostream>using namespace std;/************************************************************************//* 以下是图的邻接矩阵存储 *//************************************************************************/typedef char VertexType;//顶点数据类型 typedef int EdgeType;//边上的权值数据类型 const int MAXVEX = 100;//最大顶点数 const int INFINITY = 65535;//代表无穷大 typedef struct { VertexType vexs[MAXVEX];//顶点表 EdgeType arc[MAXVEX][MAXVEX];//邻接矩阵,可看作边表 int numVertexes, numEdges;//图中当前的顶点数和边数 }MGraph; void CreateMGraph(MGraph *G) { int i,j,k,w; printf("请输入顶点数和边数:\n"); scanf("%d,%d",&G->numVertexes,&G->numEdges); for(i=0; i<G->numVertexes; i++) { fflush(stdin); printf("请输入顶点%d的值:\n",i); scanf("%c",&G->vexs[i]); } for(i=0; i<G->numVertexes; i++)//初始化邻接表 { for(j=0; j<G->numVertexes; j++) { if(i == j) G->arc[i][j] = 0; else G->arc[i][j] = INFINITY; } } for(k=0; k<G->numEdges; k++)//在邻接表中写入具体数据 { printf("请输入边(vi,vj)上的下标i,j和权w:\n"); scanf("%d,%d,%d",&i,&j,&w); G->arc[i][j] = w; G->arc[j][i] = G->arc[i][j];//因为是无向图,矩阵对称 } } /************************************************************************//* 以下是DFS *//************************************************************************///const int MAX = 100;bool visited[MAXVEX];void DFS(MGraph G,int i){int j;visited[i] = true;printf("%c ",G.vexs[i]);for(j=0; j<G.numVertexes; j++)if(1==G.arc[i][j] && !visited[j])//这里为简洁,构造图的时候权值都设为了1DFS(G,j);}void DFSTraverse(MGraph G){ int i; for (i=0; i<G.numVertexes; i++) { visited[i] = false; } for (i=0; i<G.numVertexes; i++) { if (!visited[i]) {DFS(G,i); } }}int main(){ MGraph G; CreateMGraph(&G); for(int i=0; i<G.numVertexes; i++) { for(int j=0; j<G.numVertexes; j++) { printf("%d ",G.arc[i][j]); } printf("\n"); } DFSTraverse(G); printf("\n"); getchar(); return 0;}结果
对于图的邻接表结构,只是将数据换成了链表。如下:
#include<iostream> using namespace std; typedef char VertexType;//顶点数据类型 typedef int EdgeType;//边上的权值数据类型 const int MAXVEX = 100;//最大顶点数 const int INFINITY = 65535;//代表无穷大 typedef struct EdgeNode//边表结点 { int adjvex;//邻接点域,存储该点对应的下标 EdgeType weight;//存储权值,对于非网图可以不需要 struct EdgeNode *next; //链域,指向下一个邻接点 }EdgeNode; typedef struct VertexNode//顶点表结点 { VertexType data; EdgeNode *firstedge; }VertexNode,AdjList[MAXVEX]; typedef struct//图结构 { AdjList adjList; int numVertexes,numEdges; }GraphAdjList; void CreateALGraph(GraphAdjList *G) { int i,j,k,w; EdgeNode *e; printf("输入顶点数和边数:\n"); scanf("%d,%d",&G->numVertexes,&G->numEdges); for(i=0; i<G->numVertexes; i++) { fflush(stdin); printf("请输入顶点%d的值\n",i); scanf("%c",&G->adjList[i].data); G->adjList[i].firstedge = NULL; }for (k=0; k<G->numEdges; k++) { fflush(stdin); printf("请输入边(vi,vj)上的下标i,j和权w:\n"); scanf("%d,%d,%d",&i,&j,&w); e = (EdgeNode *)malloc(sizeof(EdgeNode)); e->adjvex = j; e->weight = w; e->next = G->adjList[i].firstedge; G->adjList[i].firstedge = e; e = (EdgeNode *)malloc(sizeof(EdgeNode));//无向图[i][j]与[j][i]权值相同,可以一次将i->j与j->i都进行赋值,如果是有向图则只需要一次赋值 e->adjvex = i; e->weight = w; e->next = G->adjList[j].firstedge; G->adjList[j].firstedge = e; } } /************************************************************************//* 以下为DFS *//************************************************************************/bool visited[MAXVEX];void DFS(GraphAdjList GL,int i){ EdgeNode *p; visited[i] = true; printf("%c ",GL.adjList[i].data); p = GL.adjList[i].firstedge; while(p) { if(!visited[p->adjvex]) DFS(GL,p->adjvex); p = p->next; }}void DFSTraverse(GraphAdjList GL){ int i; for(i=0; i<GL.numVertexes; i++) { visited[i] = false; } for (i=0; i<GL.numVertexes; i++) { if(!visited[i]) DFS(GL,i); }}int main() { GraphAdjList graphA; CreateALGraph(&graphA); for (int i=0; i<graphA.numVertexes; i++) { cout<<graphA.adjList[i].data<<"-> "; EdgeNode *tempNode = graphA.adjList[i].firstedge; while (NULL != tempNode) { cout<<"["<< tempNode->adjvex<<"]["<<tempNode->weight<<"]->"; tempNode = tempNode->next; } tempNode = NULL; cout<<endl; }DFSTraverse(graphA);cout<<endl;return 0; }结果:
以上由于链表使用了头插法,所以结果与邻接表的不一样,如果采用尾插法,就一样了。
邻接矩阵是2维数据,查找每个顶点需要访问矩阵中的所有元素,因此都需要O(n^2)的时间。
邻接表打邻接点所需要的时间取决于顶点和边的数量,所以是O(n+e)。
显然对于点多边少的稀疏图来说,邻接表结构使得算法在时间效率上大大提高。
相关:
线性表的链式存储(链表)
图的邻接表存储结构
图的邻接矩阵存储结构
- 深度优先遍历(搜索)(DFS)
- DFS(深度优先遍历搜索解析)
- 【算法导论】图的深度优先搜索遍历(DFS)
- 深度优先搜索遍历(DFS)——邻接矩阵存储
- DFS深度优先搜索遍历
- 深度优先搜索 (DFS)
- 深度优先搜索(DFS)
- 深度优先搜索(DFS)
- DFS(深度优先搜索)
- 深度优先搜索(dfs)
- DFS(深度优先搜索)
- 深度优先搜索 (DFS)
- 深度优先搜索(DFS)
- 深度优先搜索(dfs)
- 深度优先搜索(dfs)
- 深度优先搜索(dfs)
- 深度优先搜索(DFS)
- 深度优先搜索(DFS)
- 虚同步(Virtual Synchrony)核心文献
- 统计一篇英文文章中出现次数最多的前五个单词
- Android WebService(基于SOAP协议)
- 用Java23种设计模式泡MM
- ORA-28056: Writing audit records to Windows Event Log failed解决办法
- 深度优先遍历(搜索)(DFS)
- Web 前端框架 QUI v3.0 发布
- C++各种相似对象的区别
- mygridview 四宫格
- iPhone开发中经常用到的控件尺寸大集合
- 序列的排序
- Android 文件监听
- Java中怎么将Long类型转换成Integer或int类型
- C# 在线PDF阅读