数据结构(29)图的遍历

来源:互联网 发布:win7 upnp nat端口失败 编辑:程序博客网 时间:2024/05/16 05:28

图的遍历,首先说下定义:

       

       而在这里,就给大家叙述下深度优先遍历。本来是要用自己的话来给大家讲解的,但是搜了下网上的定义,觉得还是网上的定义更可靠和严谨,所以就摘取了百度百科的说明:

       假设给定图G的初态是所有顶点均未曾访问过。在G中任选一顶点v为初始出发点(源点),则深度优先遍历可定义如下:首先访问出发点v,并将其标记为已访问过;然后依次从v出发搜索v的每个邻接点w。若w未曾访问过,则以w为新的出发点继续进行深度优先遍历,直至图中所有和源点v有路径相通的顶点(亦称为从源点可达的顶点)均已被访问为止。若此时图中仍有未访问的顶点,则另选一个尚未访问的顶点作为新的源点重复上述过程,直至图中所有顶点均已被访问为止。

       图的深度优先遍历类似于树的前序遍历。采用的搜索方法的特点是尽可能先对纵深方向进行搜索。这种搜索方法称为深度优先搜索(Depth-First Search)。相应地,用此方法遍历图就很自然地称之为图的深度优先遍历。

如图:

       

       然后看下算法思想,其实在上述定义中也说过,现在来总结下:

       

      首先发下用邻接链表法实现的深度优先遍历代码(如果不理解邻接链表法,请在本博客数据结构系列中查找,里面有详细介绍),代码是基于本博客数据结构系列讲解邻接链表法实现图写的,大家可以把这段代码加在那些代码中就可以运行:

[cpp] view plaincopy
  1. static void recursive_dfs(TLGraph* graph, int v, int visited[], LGraph_Printf* pFunc)  
  2. {  
  3.     int i = 0;  
  4.       
  5.     pFunc(graph->v[v]);  
  6.       
  7.     visited[v] = 1;  
  8.       
  9.     printf(", ");  
  10.       
  11.     for(i=0; i<LinkList_Length(graph->la[v]); i++)  
  12.     {  
  13.         TListNode* node = (TListNode*)LinkList_Get(graph->la[v], i);  
  14.           
  15.         if( !visited[node->v] )  
  16.         {  
  17.             recursive_dfs(graph, node->v, visited, pFunc);  
  18.         }  
  19.     }  
  20. }  
  21.   
  22. void LGraph_DFS(LGraph* graph, int v, LGraph_Printf* pFunc)  
  23. {  
  24.     TLGraph* tGraph = (TLGraph*)graph;  
  25.     int* visited = NULL;  
  26.     int condition = (tGraph != NULL);  
  27.       
  28.     condition = condition && (0 <= v) && (v < tGraph->count);  
  29.     condition = condition && (pFunc != NULL);  
  30.     condition = condition && ((visited = (int*)calloc(tGraph->count, sizeof(int))) != NULL);  
  31.       
  32.     if( condition )  
  33.     {  
  34.         int i = 0;  
  35.           
  36.         recursive_dfs(tGraph, v, visited, pFunc);  
  37.           
  38.         for(i=0; i<tGraph->count; i++)  
  39.         {  
  40.             if( !visited[i] )  
  41.             {  
  42.                 recursive_dfs(tGraph, i, visited, pFunc);  
  43.             }  
  44.         }  
  45.           
  46.         printf("\n");  
  47.     }  
  48.       
  49.     free(visited);  
  50. }  


 

      最后发下用邻接矩阵法实现的深度优先遍历代码(如果不理解邻接矩阵法,请在本博客数据结构系列中查找,里面有详细介绍),代码是基于本博客数据结构系列讲解邻接矩阵法实现图写的,大家可以把这段代码加在那些代码中就可以运行

[cpp] view plaincopy
  1. static void recursive_dfs(TMGraph* graph, int v, int visited[], MGraph_Printf* pFunc)  
  2. {  
  3.     int i = 0;  
  4.       
  5.     pFunc(graph->v[v]);  
  6.       
  7.     visited[v] = 1;  
  8.       
  9.     printf(", ");  
  10.       
  11.     for(i=0; i<graph->count; i++)  
  12.     {  
  13.         if( (graph->matrix[v][i] != 0) && !visited[i] )  
  14.         {  
  15.             recursive_dfs(graph, i, visited, pFunc);  
  16.         }  
  17.     }  
  18. }  
  19.   
  20. void MGraph_DFS(MGraph* graph, int v, MGraph_Printf* pFunc)  
  21. {  
  22.     TMGraph* tGraph = (TMGraph*)graph;  
  23.     int* visited = NULL;  
  24.     int condition = (tGraph != NULL);  
  25.       
  26.     condition = condition && (0 <= v) && (v < tGraph->count);  
  27.     condition = condition && (pFunc != NULL);  
  28.     condition = condition && ((visited = (int*)calloc(tGraph->count, sizeof(int))) != NULL);  
  29.       
  30.     if( condition )  
  31.     {  
  32.         int i = 0;  
  33.           
  34.         recursive_dfs(tGraph, v, visited, pFunc);  
  35.           
  36.         for(i=0; i<tGraph->count; i++)  
  37.         {  
  38.             if( !visited[i] )  
  39.             {  
  40.                 recursive_dfs(tGraph, i, visited, pFunc);  
  41.             }  
  42.         }  
  43.           
  44.         printf("\n");  
  45.     }  
  46.       
  47.     free(visited);  
  48. }  

图的广度优先遍历(BFS):


    图的广度优先搜索是树的按层次遍历的推广,它的基本思想是:首先访问初始点vi,并将其标记为已访问过,接着访问vi的所有未被访问过的邻接点 vi1,vi2, …, vi t,并均标记已访问过,然后再按照vi1,vi2, …, vi t的次序,访问每一个顶点的所有未被访问过的邻接点,并均标记为已访问过,依次类推,直到图中所有和初始点vi有路径相通的顶点都被访问过为止。

如图:

 

       首先发下用邻接链表法实现的广度优先遍历代码如果不理解邻接链表法,请在本博客数据结构系列中查找,里面有详细介绍),代码是基于本博客数据结构系列讲解邻接链表法实现图写的,大家可以把这段代码加在那些代码中就可以运行:

[cpp] view plaincopy
  1. static void recursive_bfs(TLGraph* tGraph, int v, int visited[], LGraph_Printf* pFunc)  
  2. {  
  3.     LinkQueue* queue = LinkList_Create();  
  4.       
  5.     if(NULL != queue)  
  6.     {  
  7.         LinkQueue_Append(queue, tGraph->v + v);  
  8.           
  9.         while(0 < LinkQueue_Length(queue))  
  10.         {  
  11.             int i = 0;  
  12.               
  13.             v = (LVertex**)LinkQueue_Retrieve(queue) - tGraph->v;  
  14.               
  15.             pFunc(tGraph->v[v]);  
  16.               
  17.             printf(", ");  
  18.               
  19.             for(i=0; i<tGraph->la[v]; i++)  
  20.             {  
  21.                 TListNode* node = (TListNode*)LinkList_Get(tGraph->la[v], i);  
  22.                   
  23.                 if(!visited[node->v])  
  24.                 {  
  25.                     LinkQueue_Append(queue, tGraph->v + node->v);  
  26.                       
  27.                     visited[node->v] = 1;  
  28.                 }  
  29.             }  
  30.         }  
  31.     }  
  32.       
  33.     LinkQueue_Destroy(queue);  
  34. }  
  35.   
  36. void LGraph_BFS(LGraph* graph, int v, LGraph_Printf* pFunc)  
  37. {  
  38.     TLGraph* tGraph = (TLGraph*)graph;  
  39.       
  40.     int* visited = NULL;  
  41.       
  42.     int condition = (NULL != tGraph);  
  43.     condition = condition && (0 <= v) && (v < tGraph->count);  
  44.     condition = condition && (NULL != pFunc);  
  45.     condition = condition && (NULL != (visited = (int*)calloc(tGraph->count, sizeof(int))));  
  46.       
  47.     if(condition)  
  48.     {  
  49.         int i = 0;  
  50.           
  51.         recursive_bfs(tGraph, v, visited, pFunc);  
  52.           
  53.         for(i=0; i<tGraph->count; i++)  
  54.         {  
  55.             if(!visited[i])  
  56.             {  
  57.                 recursive_bfs(tGraph, i, visited, pFunc);  
  58.             }  
  59.         }  
  60.           
  61.         printf("\n");  
  62.     }  
  63.       
  64.     free(visited);  
  65. }  


 

最后发下用邻接矩阵法实现的广度优先遍历代码如果不理解邻接矩阵法,请在本博客数据结构系列中查找,里面有详细介绍),代码是基于本博客数据结构系列讲解邻接矩阵法实现图写的,大家可以把这段代码加在那些代码中就可以运行:    

[cpp] view plaincopy
  1. static void recursive_bfs(TMGraph* tGraph, int v, int visited[], MGraph_Printf* pFunc)  
  2. {  
  3.     LinkQueue* queue = LinkQueue_Create();  
  4.       
  5.     if(NULL != queue)  
  6.     {  
  7.         LinkQueue_Append(queue, tGraph->v + v);  
  8.           
  9.         visited[v] = 1;  
  10.           
  11.         while(0 < LinkQueue_Length(queue))  
  12.         {  
  13.             int i = 0;  
  14.               
  15.             v = (MVertex**)LinkQueue_Retrieve(queue) - tGraph->v;  
  16.               
  17.             pFunc(tGraph->v[v]);  
  18.               
  19.             printf(", ");  
  20.               
  21.             for(i=0; i<tGraph->count; i++)  
  22.             {  
  23.                 if((0 != tGraph->matrix[v][i]) && (!visited[i]))  
  24.                 {  
  25.                     LinkQueue_Append(queue, tGraph->v + i);  
  26.                       
  27.                     visited[i] = 1;  
  28.                 }  
  29.             }  
  30.         }  
  31.     }  
  32.       
  33.     LinkQueue_Destroy(queue);  
  34. }  
  35.   
  36. void MGraph_BFS(MGraph* graph, int v, MGraph_Printf* pFunc)  
  37. {  
  38.     TMGraph* tGraph = (TMGraph*)graph;  
  39.       
  40.     int* visited = NULL;  
  41.       
  42.     int condition = (NULL != tGraph);  
  43.     condition = condition && (0 <= v) && (v < tGraph->count);  
  44.     condition = condition && (NULL != pFunc);  
  45.     condition = condition && (NULL != (visited = (int*)calloc(tGraph->count, sizeof(int))));  
  46.       
  47.     if(condition)  
  48.     {  
  49.         int i = 0;  
  50.           
  51.         recursive_bfs(tGraph, v, visited, pFunc);  
  52.           
  53.         for(i=0; i<tGraph->count; i++)  
  54.         {  
  55.             if(!visited[i])  
  56.             {  
  57.                 recursive_bfs(tGraph, i, visited, pFunc);  
  58.             }  
  59.         }  
  60.           
  61.         printf("\n");  
  62.     }  
  63.       
  64.     free(visited);   
  65. }  


 

前面已经说了图的深度优先遍历算法,是用递归实现的,而在这里就讲一下用非递归实现,需要借助栈:

 

算法思想:

       1. 栈初始化

       2. 输出起始顶点,起始顶点改为“已访问”标志,将起始顶点进栈

       3. 重复下列操作直到栈为空:

                 3.1 取栈顶元素顶点

                 3.2 栈顶元素顶点存在未被访问过的邻接点w,则:

                                3.2.1  输出顶点w

                                3.2.2  将顶点w改为“已访问”标志

                                3.2.3  将顶点w进栈

                 3.3 否则,当前顶点出栈

 

        非递归实现深度优先遍历(邻接链表法)

[cpp] view plaincopy
  1. static void orther_dfs(TLGraph* tGraph, int v, int visited[], LGraph_Printf* pFunc)  
  2. {  
  3.     LinkStack* stack = LinkStack_Create();  
  4.       
  5.     LinkStack_Push(stack, tGraph->v + v);  
  6.       
  7.     while(!LinkStack_Empty(stack))  
  8.     {  
  9.         int w = (LVertex**)LinkStack_Top(stack) - tGraph->v;  
  10.           
  11.         LinkStack_Pop(stack);  
  12.           
  13.         if(!visited[w])  
  14.         {  
  15.             int i = 0;  
  16.               
  17.             pFunc(tGraph->v[w]);  
  18.               
  19.             visited[w] = 1;  
  20.               
  21.             for(i=0; i<LinkList_Length(tGraph->la[v]); i++)  
  22.             {  
  23.                 if(!visited[i])  
  24.                 {  
  25.                     LinkStack_Push(stack, tGraph->v + i);  
  26.                 }  
  27.             }  
  28.         }  
  29.     }  
  30.       
  31.     LinkStack_Destroy(stack);     
  32. }  
  33.   
  34. void LGraph_DFS_Orther(LGraph* graph, int v, LGraph_Printf* pFunc)  
  35. {  
  36.     TLGraph* tGraph = (TLGraph*)graph;  
  37.       
  38.     int* visited = NULL;  
  39.       
  40.     int condition = (NULL != tGraph);  
  41.     condition = condition && (0 <= v) && (v < tGraph->count);  
  42.     condition = condition && (NULL != pFunc);  
  43.     condition = condition && (NULL != (visited = (int*)calloc(tGraph->count, sizeof(int))));  
  44.       
  45.     if(condition)  
  46.     {  
  47.         int i = 0;  
  48.           
  49.         orther_dfs(tGraph, v, visited, pFunc);  
  50.           
  51.         for(i=0; i<tGraph->count; i++)  
  52.         {  
  53.             if(!visited[i])  
  54.             {  
  55.                 orther_dfs(tGraph, i, visited, pFunc);  
  56.             }  
  57.         }  
  58.           
  59.         printf("\n");  
  60.     }  
  61.       
  62.     free(visited);  
  63. }  


 

 

        非递归实现深度优先遍历(邻接矩阵法)

       

[cpp] view plaincopy
  1. static void orther_dfs(TMGraph* tGraph, int v, int visited[], MGraph_Printf* pFunc)  
  2. {  
  3.     LinkStack* stack = LinkStack_Create();  
  4.       
  5.     LinkStack_Push(stack, tGraph->v + v);  
  6.       
  7.     while(!LinkStack_Empty(stack))  
  8.     {  
  9.         int w = (MVertex**)LinkStack_Top(stack) - tGraph->v;  
  10.           
  11.         LinkStack_Pop(stack);  
  12.           
  13.         if(!visited[w])  
  14.         {  
  15.             int i = 0;  
  16.               
  17.             pFunc(tGraph->v[w]);  
  18.               
  19.             visited[w] = 1;  
  20.               
  21.             for(i=0; i<LinkList_Length(tGraph->count); i++)  
  22.             {  
  23.                 if((0!=tGraph->matrix[v][i]) && (!visited[i]))  
  24.                 {  
  25.                     LinkStack_Push(stack, tGraph->v + i);  
  26.                 }  
  27.             }  
  28.         }  
  29.     }  
  30.       
  31.     LinkStack_Destroy(stack);     
  32. }  
  33.   
  34. void MGraph_DFS_Orther(MGraph* graph, int v, MGraph_Printf* pFunc)  
  35. {  
  36.     TMGraph* tGraph = (TMGraph*)graph;  
  37.       
  38.     int* visited = NULL;  
  39.       
  40.     int condition = (NULL != tGraph);  
  41.     condition = condition && (0 <= v) && (v < tGraph->count);  
  42.     condition = condition && (NULL != pFunc);  
  43.     condition = condition && (NULL != (visited = (int*)calloc(tGraph->count, sizeof(int))));  
  44.       
  45.     if(condition)  
  46.     {  
  47.         int i = 0;  
  48.           
  49.         orther_dfs(tGraph, v, visited, pFunc);  
  50.           
  51.         for(i=0; i<tGraph->count; i++)  
  52.         {  
  53.             if(!visited[i])  
  54.             {  
  55.                 orther_dfs(tGraph, i, visited, pFunc);  
  56.             }  
  57.         }  
  58.           
  59.         printf("\n");  
  60.     }  
  61.       
  62.     free(visited);  
  63. }  


 


0 0