數據結構(29)圖的遍歷


圖的遍歷,首先說下定義:

       

       而在這里,就給大家敘述下深度優先遍歷。本來是要用自己的話來給大家講解的,但是搜了下網上的定義,覺得還是網上的定義更可靠和嚴謹,所以就摘取了百度百科的說明:

       假設給定圖G的初態是所有頂點均未曾訪問過。在G中任選一頂點v為初始出發點(源點),則深度優先遍歷可定義如下:首先訪問出發點v,並將其標記為已訪問過;然后依次從v出發搜索v的每個鄰接點w。若w未曾訪問過,則以w為新的出發點繼續進行深度優先遍歷,直至圖中所有和源點v有路徑相通的頂點(亦稱為從源點可達的頂點)均已被訪問為止。若此時圖中仍有未訪問的頂點,則另選一個尚未訪問的頂點作為新的源點重復上述過程,直至圖中所有頂點均已被訪問為止。

       圖的深度優先遍歷類似於樹的前序遍歷。采用的搜索方法的特點是盡可能先對縱深方向進行搜索。這種搜索方法稱為深度優先搜索(Depth-First Search)。相應地,用此方法遍歷圖就很自然地稱之為圖的深度優先遍歷。

如圖:

       

       然后看下算法思想,其實在上述定義中也說過,現在來總結下:

       

      首先發下用鄰接鏈表法實現的深度優先遍歷代碼(如果不理解鄰接鏈表法,請在本博客數據結構系列中查找,里面有詳細介紹),代碼是基於本博客數據結構系列講解鄰接鏈表法實現圖寫的,大家可以把這段代碼加在那些代碼中就可以運行:

[cpp]  view plain copy
  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 plain copy
  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 plain copy
  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 plain copy
  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 plain copy
  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 plain copy
  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. }  


 



注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com