数据结构(29)图的遍历
来源:互联网 发布:win7 upnp nat端口失败 编辑:程序博客网 时间:2024/05/16 05:28
图的遍历,首先说下定义:
而在这里,就给大家叙述下深度优先遍历。本来是要用自己的话来给大家讲解的,但是搜了下网上的定义,觉得还是网上的定义更可靠和严谨,所以就摘取了百度百科的说明:
假设给定图G的初态是所有顶点均未曾访问过。在G中任选一顶点v为初始出发点(源点),则深度优先遍历可定义如下:首先访问出发点v,并将其标记为已访问过;然后依次从v出发搜索v的每个邻接点w。若w未曾访问过,则以w为新的出发点继续进行深度优先遍历,直至图中所有和源点v有路径相通的顶点(亦称为从源点可达的顶点)均已被访问为止。若此时图中仍有未访问的顶点,则另选一个尚未访问的顶点作为新的源点重复上述过程,直至图中所有顶点均已被访问为止。
图的深度优先遍历类似于树的前序遍历。采用的搜索方法的特点是尽可能先对纵深方向进行搜索。这种搜索方法称为深度优先搜索(Depth-First Search)。相应地,用此方法遍历图就很自然地称之为图的深度优先遍历。
如图:
然后看下算法思想,其实在上述定义中也说过,现在来总结下:
首先发下用邻接链表法实现的深度优先遍历代码(如果不理解邻接链表法,请在本博客数据结构系列中查找,里面有详细介绍),代码是基于本博客数据结构系列讲解邻接链表法实现图写的,大家可以把这段代码加在那些代码中就可以运行:
- static void recursive_dfs(TLGraph* graph, int v, int visited[], LGraph_Printf* pFunc)
- {
- int i = 0;
- pFunc(graph->v[v]);
- visited[v] = 1;
- printf(", ");
- for(i=0; i<LinkList_Length(graph->la[v]); i++)
- {
- TListNode* node = (TListNode*)LinkList_Get(graph->la[v], i);
- if( !visited[node->v] )
- {
- recursive_dfs(graph, node->v, visited, pFunc);
- }
- }
- }
- void LGraph_DFS(LGraph* graph, int v, LGraph_Printf* pFunc)
- {
- TLGraph* tGraph = (TLGraph*)graph;
- int* visited = NULL;
- int condition = (tGraph != NULL);
- condition = condition && (0 <= v) && (v < tGraph->count);
- condition = condition && (pFunc != NULL);
- condition = condition && ((visited = (int*)calloc(tGraph->count, sizeof(int))) != NULL);
- if( condition )
- {
- int i = 0;
- recursive_dfs(tGraph, v, visited, pFunc);
- for(i=0; i<tGraph->count; i++)
- {
- if( !visited[i] )
- {
- recursive_dfs(tGraph, i, visited, pFunc);
- }
- }
- printf("\n");
- }
- free(visited);
- }
最后发下用邻接矩阵法实现的深度优先遍历代码(如果不理解邻接矩阵法,请在本博客数据结构系列中查找,里面有详细介绍),代码是基于本博客数据结构系列讲解邻接矩阵法实现图写的,大家可以把这段代码加在那些代码中就可以运行:
- static void recursive_dfs(TMGraph* graph, int v, int visited[], MGraph_Printf* pFunc)
- {
- int i = 0;
- pFunc(graph->v[v]);
- visited[v] = 1;
- printf(", ");
- for(i=0; i<graph->count; i++)
- {
- if( (graph->matrix[v][i] != 0) && !visited[i] )
- {
- recursive_dfs(graph, i, visited, pFunc);
- }
- }
- }
- void MGraph_DFS(MGraph* graph, int v, MGraph_Printf* pFunc)
- {
- TMGraph* tGraph = (TMGraph*)graph;
- int* visited = NULL;
- int condition = (tGraph != NULL);
- condition = condition && (0 <= v) && (v < tGraph->count);
- condition = condition && (pFunc != NULL);
- condition = condition && ((visited = (int*)calloc(tGraph->count, sizeof(int))) != NULL);
- if( condition )
- {
- int i = 0;
- recursive_dfs(tGraph, v, visited, pFunc);
- for(i=0; i<tGraph->count; i++)
- {
- if( !visited[i] )
- {
- recursive_dfs(tGraph, i, visited, pFunc);
- }
- }
- printf("\n");
- }
- free(visited);
- }
图的广度优先遍历(BFS):
图的广度优先搜索是树的按层次遍历的推广,它的基本思想是:首先访问初始点vi,并将其标记为已访问过,接着访问vi的所有未被访问过的邻接点 vi1,vi2, …, vi t,并均标记已访问过,然后再按照vi1,vi2, …, vi t的次序,访问每一个顶点的所有未被访问过的邻接点,并均标记为已访问过,依次类推,直到图中所有和初始点vi有路径相通的顶点都被访问过为止。
如图:
首先发下用邻接链表法实现的广度优先遍历代码(如果不理解邻接链表法,请在本博客数据结构系列中查找,里面有详细介绍),代码是基于本博客数据结构系列讲解邻接链表法实现图写的,大家可以把这段代码加在那些代码中就可以运行::
- static void recursive_bfs(TLGraph* tGraph, int v, int visited[], LGraph_Printf* pFunc)
- {
- LinkQueue* queue = LinkList_Create();
- if(NULL != queue)
- {
- LinkQueue_Append(queue, tGraph->v + v);
- while(0 < LinkQueue_Length(queue))
- {
- int i = 0;
- v = (LVertex**)LinkQueue_Retrieve(queue) - tGraph->v;
- pFunc(tGraph->v[v]);
- printf(", ");
- for(i=0; i<tGraph->la[v]; i++)
- {
- TListNode* node = (TListNode*)LinkList_Get(tGraph->la[v], i);
- if(!visited[node->v])
- {
- LinkQueue_Append(queue, tGraph->v + node->v);
- visited[node->v] = 1;
- }
- }
- }
- }
- LinkQueue_Destroy(queue);
- }
- void LGraph_BFS(LGraph* graph, int v, LGraph_Printf* pFunc)
- {
- TLGraph* tGraph = (TLGraph*)graph;
- int* visited = NULL;
- int condition = (NULL != tGraph);
- condition = condition && (0 <= v) && (v < tGraph->count);
- condition = condition && (NULL != pFunc);
- condition = condition && (NULL != (visited = (int*)calloc(tGraph->count, sizeof(int))));
- if(condition)
- {
- int i = 0;
- recursive_bfs(tGraph, v, visited, pFunc);
- for(i=0; i<tGraph->count; i++)
- {
- if(!visited[i])
- {
- recursive_bfs(tGraph, i, visited, pFunc);
- }
- }
- printf("\n");
- }
- free(visited);
- }
最后发下用邻接矩阵法实现的广度优先遍历代码(如果不理解邻接矩阵法,请在本博客数据结构系列中查找,里面有详细介绍),代码是基于本博客数据结构系列讲解邻接矩阵法实现图写的,大家可以把这段代码加在那些代码中就可以运行:
- static void recursive_bfs(TMGraph* tGraph, int v, int visited[], MGraph_Printf* pFunc)
- {
- LinkQueue* queue = LinkQueue_Create();
- if(NULL != queue)
- {
- LinkQueue_Append(queue, tGraph->v + v);
- visited[v] = 1;
- while(0 < LinkQueue_Length(queue))
- {
- int i = 0;
- v = (MVertex**)LinkQueue_Retrieve(queue) - tGraph->v;
- pFunc(tGraph->v[v]);
- printf(", ");
- for(i=0; i<tGraph->count; i++)
- {
- if((0 != tGraph->matrix[v][i]) && (!visited[i]))
- {
- LinkQueue_Append(queue, tGraph->v + i);
- visited[i] = 1;
- }
- }
- }
- }
- LinkQueue_Destroy(queue);
- }
- void MGraph_BFS(MGraph* graph, int v, MGraph_Printf* pFunc)
- {
- TMGraph* tGraph = (TMGraph*)graph;
- int* visited = NULL;
- int condition = (NULL != tGraph);
- condition = condition && (0 <= v) && (v < tGraph->count);
- condition = condition && (NULL != pFunc);
- condition = condition && (NULL != (visited = (int*)calloc(tGraph->count, sizeof(int))));
- if(condition)
- {
- int i = 0;
- recursive_bfs(tGraph, v, visited, pFunc);
- for(i=0; i<tGraph->count; i++)
- {
- if(!visited[i])
- {
- recursive_bfs(tGraph, i, visited, pFunc);
- }
- }
- printf("\n");
- }
- free(visited);
- }
前面已经说了图的深度优先遍历算法,是用递归实现的,而在这里就讲一下用非递归实现,需要借助栈:
算法思想:
1. 栈初始化
2. 输出起始顶点,起始顶点改为“已访问”标志,将起始顶点进栈
3. 重复下列操作直到栈为空:
3.1 取栈顶元素顶点
3.2 栈顶元素顶点存在未被访问过的邻接点w,则:
3.2.1 输出顶点w
3.2.2 将顶点w改为“已访问”标志
3.2.3 将顶点w进栈
3.3 否则,当前顶点出栈
非递归实现深度优先遍历(邻接链表法)
- static void orther_dfs(TLGraph* tGraph, int v, int visited[], LGraph_Printf* pFunc)
- {
- LinkStack* stack = LinkStack_Create();
- LinkStack_Push(stack, tGraph->v + v);
- while(!LinkStack_Empty(stack))
- {
- int w = (LVertex**)LinkStack_Top(stack) - tGraph->v;
- LinkStack_Pop(stack);
- if(!visited[w])
- {
- int i = 0;
- pFunc(tGraph->v[w]);
- visited[w] = 1;
- for(i=0; i<LinkList_Length(tGraph->la[v]); i++)
- {
- if(!visited[i])
- {
- LinkStack_Push(stack, tGraph->v + i);
- }
- }
- }
- }
- LinkStack_Destroy(stack);
- }
- void LGraph_DFS_Orther(LGraph* graph, int v, LGraph_Printf* pFunc)
- {
- TLGraph* tGraph = (TLGraph*)graph;
- int* visited = NULL;
- int condition = (NULL != tGraph);
- condition = condition && (0 <= v) && (v < tGraph->count);
- condition = condition && (NULL != pFunc);
- condition = condition && (NULL != (visited = (int*)calloc(tGraph->count, sizeof(int))));
- if(condition)
- {
- int i = 0;
- orther_dfs(tGraph, v, visited, pFunc);
- for(i=0; i<tGraph->count; i++)
- {
- if(!visited[i])
- {
- orther_dfs(tGraph, i, visited, pFunc);
- }
- }
- printf("\n");
- }
- free(visited);
- }
非递归实现深度优先遍历(邻接矩阵法)
- static void orther_dfs(TMGraph* tGraph, int v, int visited[], MGraph_Printf* pFunc)
- {
- LinkStack* stack = LinkStack_Create();
- LinkStack_Push(stack, tGraph->v + v);
- while(!LinkStack_Empty(stack))
- {
- int w = (MVertex**)LinkStack_Top(stack) - tGraph->v;
- LinkStack_Pop(stack);
- if(!visited[w])
- {
- int i = 0;
- pFunc(tGraph->v[w]);
- visited[w] = 1;
- for(i=0; i<LinkList_Length(tGraph->count); i++)
- {
- if((0!=tGraph->matrix[v][i]) && (!visited[i]))
- {
- LinkStack_Push(stack, tGraph->v + i);
- }
- }
- }
- }
- LinkStack_Destroy(stack);
- }
- void MGraph_DFS_Orther(MGraph* graph, int v, MGraph_Printf* pFunc)
- {
- TMGraph* tGraph = (TMGraph*)graph;
- int* visited = NULL;
- int condition = (NULL != tGraph);
- condition = condition && (0 <= v) && (v < tGraph->count);
- condition = condition && (NULL != pFunc);
- condition = condition && (NULL != (visited = (int*)calloc(tGraph->count, sizeof(int))));
- if(condition)
- {
- int i = 0;
- orther_dfs(tGraph, v, visited, pFunc);
- for(i=0; i<tGraph->count; i++)
- {
- if(!visited[i])
- {
- orther_dfs(tGraph, i, visited, pFunc);
- }
- }
- printf("\n");
- }
- free(visited);
- }
- 数据结构(29)图的遍历
- 数据结构(图的遍历)
- 图的遍历(数据结构)
- 图的遍历 - 数据结构
- 数据结构---->图的遍历
- 图的遍历 - 数据结构
- 数据结构 - 图的遍历
- 【数据结构】图的遍历
- 数据结构-图的遍历
- 数据结构(C++)<图的深度遍历和广度遍历>
- 数据结构--图的遍历(二)
- 数据结构----图的遍历(DFS)
- 数据结构 图 图的遍历
- 数据结构之图的遍历
- 数据结构之图的遍历
- 数据结构之图的遍历
- 数据结构:树、图的遍历
- 数据结构(图遍历--广度优先遍历)
- 语义分析的一些方法(三) 图像语义分析
- 取余与位运算
- 拼写纠错 (英文)
- IOS FMDB操作SQLite3
- Eclipse导入项目被认为不是Web项目无法部署到Tomcat服务器上的最简单解决办法
- 数据结构(29)图的遍历
- 手机系统版本跳转
- 华为OJ(查找组成一个偶数最接近的两个素数)
- LeetCode-29 Divide Two Integers
- linux中用进程的PID来查找执行文件的及其路径
- 关于同一个数据库的表备份和表恢复的sql简单语句
- java 动态代理
- 74.明明的随机数
- Struts2基础---struts.xml配置