图的广度优先遍历BFS(分别以邻接矩阵和邻接链表实现)

算法描述:

          设图G的初始状态是所有顶点均未被访问过,在G中的任选一顶点vi为初始出发点,则广度优先遍历 可定义如下:首先,访问初始出发点vi,接着依次访问vi的所有邻接点w1,w2,...,wk;然后,依次访问w1,w2,...,wk 的邻接的所有未被访问过的顶点,依次类推,直到图中所有的和初始点vi有路径相通的顶点都被访问过为止。

算法实现:

           (1) 访问初始顶点vi

          (2) 置顶点v已访问标记

          (3) 顶点v入队

          (4) while(队不空){

                   取出队首顶点i;

                   依次搜索顶点i的所有的邻接点;

                   如果未被访问,则访问该邻接点,并将其入队。

           }

               

               用邻接矩阵实现图的广度优先遍历的源代码如下:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 广度遍历图 
  3.  **/  
  4. void BFS_MG(MGraph MG,int s){  
  5.     //清空访问标志  
  6.     init_Visit();  
  7.     //定义队列,用于保存当前节点的邻接顶点  
  8.     int Q[MAX_VEX_NUM];  
  9.     int front = 0;  
  10.     int rear = 0;  
  11.     int i,j,k;  
  12.     printf("%c\t",MG.vexs[s]);  
  13.     visit[s] = 1;  
  14.     Q[rear++] = s;  
  15.     //遍历队列   
  16.     while(front < rear){  
  17.         i = Q[front++];  
  18.         for (j = 1; j <= MG.vexnum;j++){  
  19.             if(visit[j] == 0 && MG.arcs[i][j] == 1){  
  20.                 printf("%c\t",MG.vexs[j]);  
  21.                 visit[j] = 1;  
  22.                 Q[rear++] = j;  
  23.             }  
  24.               
  25.         }  
  26.     }  
  27. }  

         用邻接表实现图的广度优先遍历的源代码如下:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 广度遍历图 
  3.  **/  
  4. void BFS_AG(ALGraph AG,int s){  
  5.     ArcPtr p;  
  6.     //清空访问标志  
  7.     init_Visit();  
  8.     //定义队列,用于保存当前节点的邻接顶点  
  9.     int Q[MAX_VERTEX_NUM];  
  10.     int front = 0;  
  11.     int rear = 0;  
  12.     int i,j,k;  
  13.     printf("%c\t",AG.vertices[s]);  
  14.     visit[s] = 1;  
  15.     Q[rear++] = s;  
  16.     //遍历队列   
  17.     while(front < rear){  
  18.         i = Q[front++];  
  19.     for(p = AG.vertices[i].firstarc;p;p=p->nextarc){  
  20.             j = p->adjvex;  
  21.             if(visit[j] == 0){  
  22.                 printf("%c\t",AG.vertices[j].vexdata);  
  23.                 visit[j] = 1;  
  24.                 Q[rear++] = j;  
  25.             }  
  26.               
  27.         }  
  28.     }  
  29. }  

算法说明:  

        对有具有n个顶点和e条边的连通图,因为每个基点均需要入队一次,所以while语句需要执行n次,对于邻接矩阵而言,内循环搜索邻接点时同样需要执行n次,故BFS_MG的时间复杂度为O(n^2);对于邻接表而言,内循环的次数取决于各顶点的边表结点的总个数,所以BFS_AG的时间复杂度为O(n+e)。

        可以看出,广度优先遍历需要一个辅助队列,和标志数组,故空间复杂度为O(n)。

       

完整代码:

           用邻接矩阵实现广度优先遍历的完整代码:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /* 
  2.  ============================================================================ 
  3.  Name        : Graph.c 
  4.  Author      : jesson20121020 
  5.  Version     : 1.0 
  6.  Description : create Graph using Adjacency Matrix, Ansi-style 
  7.  ============================================================================ 
  8.  */  
  9.   
  10. #include <stdio.h>  
  11. #include <stdlib.h>  
  12. #define MAX_VEX_NUM 50  
  13. typedef char VertexType;  
  14. typedef enum {  
  15.     DG, UDG  
  16. } GraphType;  
  17. typedef struct {  
  18.     VertexType vexs[MAX_VEX_NUM];  
  19.     int arcs[MAX_VEX_NUM][MAX_VEX_NUM];  
  20.     int vexnum, arcnum;  
  21.     GraphType type;  
  22. } MGraph;  
  23.   
  24. //设置图中顶点访问标志  
  25. int visit[MAX_VEX_NUM];  
  26.   
  27. /** 
  28.  * 根据名称得到指定顶点在顶点集合中的下标 
  29.  * vex  顶点 
  30.  * return 如果找到,则返回下标,否则,返回0 
  31.  */  
  32. int getIndexOfVexs(char vex, MGraph *MG) {  
  33.     int i;  
  34.     for (i = 1; i <= MG->vexnum; i++) {  
  35.         if (MG->vexs[i] == vex) {  
  36.             return i;  
  37.         }  
  38.     }  
  39.     return 0;  
  40. }  
  41.   
  42. /** 
  43.  * 创建邻接矩阵 
  44.  */  
  45. void create_MG(MGraph *MG) {  
  46.     int i, j, k;  
  47.     int v1, v2, type;  
  48.     char c1, c2;  
  49.     printf("Please input graph type DG(0) or UDG(1) :");  
  50.     scanf("%d", &type);  
  51.     if (type == 0)  
  52.         MG->type = DG;  
  53.     else if (type == 1)  
  54.         MG->type = UDG;  
  55.     else {  
  56.         printf("Please input correct graph type DG(0) or UDG(1)!");  
  57.         return;  
  58.     }  
  59.   
  60.     printf("Please input vexmun : ");  
  61.     scanf("%d", &MG->vexnum);  
  62.     printf("Please input arcnum : ");  
  63.     scanf("%d", &MG->arcnum);  
  64.     getchar();  
  65.     for (i = 1; i <= MG->vexnum; i++) {  
  66.         printf("Please input %dth vex(char):", i);  
  67.         scanf("%c", &MG->vexs[i]);  
  68.         getchar();  
  69.     }  
  70.   
  71.     //初始化邻接矩阵  
  72.     for (i = 1; i <= MG->vexnum; i++) {  
  73.         for (j = 1; j <= MG->vexnum; j++) {  
  74.             MG->arcs[i][j] = 0;  
  75.         }  
  76.     }  
  77.   
  78.     //输入边的信息,建立邻接矩阵  
  79.     for (k = 1; k <= MG->arcnum; k++) {  
  80.         printf("Please input %dth arc v1(char) v2(char) : ", k);  
  81.   
  82.         scanf("%c %c", &c1, &c2);  
  83.         v1 = getIndexOfVexs(c1, MG);  
  84.         v2 = getIndexOfVexs(c2, MG);  
  85.         if (MG->type == 1)  
  86.             MG->arcs[v1][v2] = MG->arcs[v2][v1] = 1;  
  87.         else  
  88.             MG->arcs[v1][v2] = 1;  
  89.         getchar();  
  90.     }  
  91. }  
  92. /** 
  93.  * 打印邻接矩阵和顶点信息 
  94.  */  
  95. void print_MG(MGraph MG) {  
  96.     int i, j;  
  97.     if(MG.type == DG){  
  98.         printf("Graph type: Direct graph\n");  
  99.     }  
  100.     else{  
  101.         printf("Graph type: Undirect graph\n");  
  102.     }  
  103.   
  104.     printf("Graph vertex number: %d\n",MG.vexnum);  
  105.     printf("Graph arc number: %d\n",MG.arcnum);  
  106.   
  107.     printf("Vertex set:\n ");  
  108.     for (i = 1; i <= MG.vexnum; i++)  
  109.         printf("%c\t", MG.vexs[i]);  
  110.     printf("\nAdjacency Matrix:\n");  
  111.   
  112.     for (i = 1; i <= MG.vexnum; i++) {  
  113.         j = 1;  
  114.         for (; j < MG.vexnum; j++) {  
  115.             printf("%d\t", MG.arcs[i][j]);  
  116.         }  
  117.         printf("%d\n", MG.arcs[i][j]);  
  118.     }  
  119. }  
  120.   
  121. /** 
  122.  * 初始化顶点访问标志 
  123.  **/  
  124. void init_Visit(){  
  125.     int i;  
  126.     for(i = 0;i < MAX_VEX_NUM;i++)  
  127.         visit[i] = 0;  
  128. }  
  129.   
  130. /** 
  131.  * 广度遍历图 
  132.  **/  
  133. void BFS_MG(MGraph MG,int s){  
  134.     //清空访问标志  
  135.     init_Visit();  
  136.     //定义队列,用于保存当前节点的邻接顶点  
  137.     int Q[MAX_VEX_NUM];  
  138.     int front = 0;  
  139.     int rear = 0;  
  140.     int i,j,k;  
  141.     printf("%c\t",MG.vexs[s]);  
  142.     visit[s] = 1;  
  143.     Q[rear++] = s;  
  144.     //遍历队列   
  145.     while(front < rear){  
  146.         i = Q[front++];  
  147.         for (j = 1; j <= MG.vexnum;j++){  
  148.             if(visit[j] == 0 && MG.arcs[i][j] == 1){  
  149.                 printf("%c\t",MG.vexs[j]);  
  150.                 visit[j] = 1;  
  151.                 Q[rear++] = j;  
  152.             }  
  153.               
  154.         }  
  155.     }  
  156. }  
  157.   
  158. /** 
  159.  * 主函数 
  160.  */  
  161. int main(void) {  
  162.     MGraph MG;  
  163.     create_MG(&MG);  
  164.     print_MG(MG);  
  165.   
  166.     printf("\nThe result of BFS:\n");  
  167.     BFS_MG(MG,1);  
  168.       
  169.     return EXIT_SUCCESS;  
  170. }  

           

           用邻接表实现广度优先遍历的完整代码:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /* 
  2.  ============================================================================ 
  3.  Name        : ALGraph.c 
  4.  Author      : jesson20121020 
  5.  Version     : 
  6.  Copyright   : Your copyright notice 
  7.  Description : Graph using linkList, Ansi-style 
  8.  ============================================================================ 
  9.  */  
  10.   
  11. #include <stdio.h>  
  12. #include <stdlib.h>  
  13.   
  14. #include <stdio.h>  
  15.   
  16. #define MAX_VERTEX_NUM 50  
  17. typedef enum {  
  18.     DG, UDG  
  19. } GraphType;  
  20. typedef char VertexType;  
  21. //表节点  
  22. typedef struct ArcNode {  
  23.     int adjvex; //邻接节点  
  24.     int weight; //边权重  
  25.     struct ArcNode *nextarc; //下一个节点指针  
  26. } ArcNode, *ArcPtr;  
  27. //头节点  
  28. typedef struct {  
  29.     VertexType vexdata;  
  30.     int id;  
  31.     ArcPtr firstarc;  
  32. } VNode;  
  33. //头节点数组  
  34. typedef struct {  
  35.     VNode vertices[MAX_VERTEX_NUM];  
  36.     int vexnum, arcnum;  
  37.     GraphType type;  
  38. } ALGraph;  
  39.   
  40. int visit[MAX_VERTEX_NUM];  
  41.   
  42. /** 
  43.  * 根据顶点字符得到在顶点数组中的下标 
  44.  */  
  45. int getIndexOfVexs(char vex, ALGraph *AG) {  
  46.     int i;  
  47.     for (i = 1; i <= AG->vexnum; i++) {  
  48.         if (AG->vertices[i].vexdata == vex) {  
  49.             return i;  
  50.         }  
  51.     }  
  52.     return 0;  
  53. }  
  54. /** 
  55.  * 创建邻接表 
  56.  */  
  57. void create_AG(ALGraph *AG) {  
  58.     ArcPtr p,q;  
  59.     int i, j, k, type;  
  60.     VertexType v1, v2;  
  61.     printf("Please input graph type UG(0) or UDG(1) :");  
  62.     scanf("%d", &type);  
  63.     if (type == 0)  
  64.         AG->type = DG;  
  65.     else if (type == 1)  
  66.         AG->type = UDG;  
  67.     else {  
  68.         printf("Please input correct graph type UG(0) or UDG(1)!");  
  69.         return;  
  70.     }  
  71.   
  72.     printf("please input vexnum:");  
  73.     scanf("%d", &AG->vexnum);  
  74.     printf("please input arcnum:");  
  75.     scanf("%d", &AG->arcnum);  
  76.     getchar();  
  77.     for (i = 1; i <= AG->vexnum; i++) {  
  78.         printf("please input the %dth vex(char) : ", i);  
  79.         scanf("%c", &AG->vertices[i].vexdata);  
  80.         getchar();  
  81.         AG->vertices[i].firstarc = NULL;  
  82.     }  
  83.   
  84.     for (k = 1; k <= AG->arcnum; k++) {  
  85.         printf("please input the %dth arc v1(char) v2(char) :", k);  
  86.         scanf("%c %c", &v1, &v2);  
  87.         i = getIndexOfVexs(v1, AG);  
  88.         j = getIndexOfVexs(v2, AG);  
  89.   
  90.         //根据图的类型创建邻接表  
  91.         //方法1,插入到链表头  
  92.         /* 
  93.         if (AG->type == DG) { //有向图 
  94.             p = (ArcPtr) malloc(sizeof(ArcNode)); 
  95.             p->adjvex = j; 
  96.             p->nextarc = AG->vertices[i].firstarc; 
  97.             AG->vertices[i].firstarc = p; 
  98.         } else { //无向图 
  99.             p = (ArcPtr) malloc(sizeof(ArcNode)); 
  100.             p->adjvex = j; 
  101.             p->nextarc = AG->vertices[i].firstarc; 
  102.             AG->vertices[i].firstarc = p; 
  103.  
  104.             p = (ArcPtr) malloc(sizeof(ArcNode)); 
  105.             p->adjvex = i; 
  106.             p->nextarc = AG->vertices[j].firstarc; 
  107.             AG->vertices[j].firstarc = p; 
  108.         } 
  109.         */  
  110.         //方法2,插入到链表尾  
  111.         if (AG->type == DG) { //有向图  
  112.             p = (ArcPtr) malloc(sizeof(ArcNode));  
  113.             p->adjvex = j;  
  114.             //表为空  
  115.             if(AG->vertices[i].firstarc == NULL){  
  116.                 AG->vertices[i].firstarc = p;  
  117.             }  
  118.             else{  
  119.                 //找最后一个表节点  
  120.                 q = AG->vertices[i].firstarc;  
  121.                 while(q->nextarc != NULL){  
  122.                     q = q->nextarc;  
  123.                 }  
  124.                 q->nextarc = p;  
  125.             }  
  126.             p->nextarc = NULL;  
  127.               
  128.         } else { //无向图  
  129.               
  130.             p = (ArcPtr) malloc(sizeof(ArcNode));  
  131.             p->adjvex = j;  
  132.             //表为空  
  133.             if(AG->vertices[i].firstarc == NULL){  
  134.                 AG->vertices[i].firstarc = p;  
  135.             }  
  136.             else{  
  137.                 //找最后一个表节点  
  138.                 q = AG->vertices[i].firstarc;  
  139.                 while(q->nextarc != NULL){  
  140.                     q = q->nextarc;  
  141.                 }  
  142.                 q->nextarc = p;  
  143.             }  
  144.             p->nextarc = NULL;  
  145.               
  146.             p = (ArcPtr) malloc(sizeof(ArcNode));  
  147.             p->adjvex = i;  
  148.             //表为空  
  149.             if(AG->vertices[j].firstarc == NULL){  
  150.                 AG->vertices[j].firstarc = p;  
  151.             }  
  152.             else{  
  153.                 //找最后一个表节点  
  154.                 q = AG->vertices[j].firstarc;  
  155.                 while(q->nextarc != NULL){  
  156.                     q = q->nextarc;  
  157.                 }  
  158.                 q->nextarc = p;  
  159.             }  
  160.             p->nextarc = NULL;  
  161.         }  
  162.           
  163.         getchar();  
  164.     }  
  165. }  
  166.   
  167. /** 
  168.  * 输出图的相关信息 
  169.  */  
  170. void print_AG(ALGraph AG) {  
  171.     ArcPtr p;  
  172.     int i;  
  173.     if (AG.type == DG) {  
  174.         printf("Graph type: Direct graph\n");  
  175.     } else {  
  176.         printf("Graph type: Undirect graph\n");  
  177.     }  
  178.   
  179.     printf("Graph vertex number: %d\n", AG.vexnum);  
  180.     printf("Graph arc number: %d\n", AG.arcnum);  
  181.   
  182.     printf("Vertex set :\n");  
  183.     for (i = 1; i <= AG.vexnum; i++)  
  184.         printf("%c\t", AG.vertices[i].vexdata);  
  185.     printf("\nAdjacency List:\n");  
  186.     for (i = 1; i <= AG.vexnum; i++) {  
  187.         printf("%d", i);  
  188.         p = AG.vertices[i].firstarc;  
  189.         while (p != NULL) {  
  190.             printf("-->%d", p->adjvex);  
  191.             p = p->nextarc;  
  192.         }  
  193.         printf("\n");  
  194.     }  
  195. }  
  196.   
  197. /** 
  198.  * 初始化顶点访问标志 
  199.  **/  
  200. void init_Visit(){  
  201.     int i;  
  202.     for(i = 0;i < MAX_VERTEX_NUM;i++)  
  203.         visit[i] = 0;  
  204. }  
  205.   
  206. /** 
  207.  * 广度遍历图 
  208.  **/  
  209. void BFS_AG(ALGraph AG,int s){  
  210.     ArcPtr p;  
  211.     //清空访问标志  
  212.     init_Visit();  
  213.     //定义队列,用于保存当前节点的邻接顶点  
  214.     int Q[MAX_VERTEX_NUM];  
  215.     int front = 0;  
  216.     int rear = 0;  
  217.     int i,j,k;  
  218.     printf("%c\t",AG.vertices[s]);  
  219.     visit[s] = 1;  
  220.     Q[rear++] = s;  
  221.     //遍历队列   
  222.     while(front < rear){  
  223.         i = Q[front++];  
  224.     for(p = AG.vertices[i].firstarc;p;p=p->nextarc){  
  225.             j = p->adjvex;  
  226.             if(visit[j] == 0){  
  227.                 printf("%c\t",AG.vertices[j].vexdata);  
  228.                 visit[j] = 1;  
  229.                 Q[rear++] = j;  
  230.             }  
  231.               
  232.         }  
  233.     }  
  234. }  
  235.   
  236. int main(void) {  
  237.     ALGraph AG;  
  238.   
  239.     create_AG(&AG);  
  240.   
  241.     print_AG(AG);  
  242.       
  243.     printf("\nThe result of BFS:\n");  
  244.     BFS_AG(AG,1);  
  245.     return EXIT_SUCCESS;  
  246. }
  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 邻接表是一种表示的数据结构,它由一个数组和一个链表组成。数组中的每个元素表示一个顶点,链表中的每个节点表示该顶点的邻居。 深度优先遍历(DFS)是一种遍历的算法,它从一个顶点开始,沿着一条路径一直走到底,直到不能再走为止,然后回溯到前一个顶点,继续走其他路径,直到所有的顶点都被访问过。 广度优先遍历BFS)是一种遍历的算法,它从一个顶点开始,先访问它的所有邻居,然后再访问邻居的邻居,直到所有的顶点都被访问过。 邻接表可以很方便地实现的深度优先遍历广度优先遍历。对于深度优先遍历,我们可以使用递归函数来实现,从一个顶点开始,依次访问它的邻居,如果邻居还没有被访问过,则递归访问邻居。对于广度优先遍历,我们可以使用队列来实现,从一个顶点开始,先将它的所有邻居加入队列中,然后依次访问队列中的顶点,将它们的邻居加入队列中,直到队列为空为止。 ### 回答2: 邻接表是一种表示的数据结构,它以链表的形式存储每一个顶点的邻接点。使用邻接实现的深度优先遍历广度优先遍历是常见的操作。 深度优先遍历(Depth First Search, DFS)可以理解为沿着一个路径走到底,直到走到末端再回溯。具体实现中,我们可以先访问起点,然后递归地遍历与其相邻的所有未访问的顶点。可以用栈来保存待遍历的顶点,每次从栈顶取出一个顶点继续遍历相邻的顶点。 广度优先遍历(Breadth First Search,BFS)可以理解为一层一层遍历,先访问当前节点所有未被访问的且未入队的邻接点,并将其入队。然后依次取出队首元素,继续进行访问和入队操作。可以用队列来保存待遍历的顶点。 邻接实现深度优先遍历的伪代码: ```python def dfs(graph, start): visited = set() # 记录访问过的节点 stack = [start] # 初始状态下栈中只有起点 while stack: # 当栈不为空时 vertex = stack.pop() # 取出栈顶元素 if vertex not in visited: visited.add(vertex) # 标记为访问过 for neighbor in graph[vertex]: # 遍历vertex的邻接点neighbor if neighbor not in visited: stack.append(neighbor) # 将未访问过的邻接点加入栈中 return visited ``` 邻接实现广度优先遍历的伪代码: ```python from collections import deque def bfs(graph, start): visited = set() # 记录访问过的节点 queue = deque([start]) # 初始状态下队列中只有起点 while queue: # 当队列不为空时 vertex = queue.popleft() # 取出队首元素 if vertex not in visited: visited.add(vertex) # 标记为访问过 for neighbor in graph[vertex]: # 遍历vertex的邻接点neighbor if neighbor not in visited: queue.append(neighbor) # 将未访问过的邻接点加入队列中 return visited ``` 邻接表的深度优先遍历广度优先遍历的时间复杂度都是O(V+E),其中V为中的顶点数,E为边数。在实际应用中,要根据具体情况选择合适的算法来遍历。 ### 回答3: 邻接表是的一种存储方式,它以每个顶点为索引,每个索引对应一个链表链表中存储该顶点相邻的其他顶点。这种存储方式适合解决大规模的问题,因为其空间复杂度与中的边数成正比。 深度优先遍历(DFS)是的一种遍历方式,它从一个顶点开始,访问该顶点的直接邻居,对邻居中未访问的顶点又进行相同的操作。当一个顶点没有未访问的邻居时,回溯到之前的顶点继续遍历邻接实现DFS可以使用递归实现,即从某个顶点开始,递归访问其邻居,直到没有未访问的邻居。 广度优先遍历BFS)则是另一种遍历方式,它从一个顶点开始,先访问其直接邻居,再依次访问邻居的邻居,直到遍历完所有的顶点。邻接实现BFS可以使用队列实现,即从某个顶点开始,将其邻居加入队列中,依次出队并访问其邻居,直到队列为空。 需要注意的是,在使用邻接实现遍历时,需要标记每个顶点是否被访问过,避免重复遍历和死循环。同时需要注意DFS和BFS的时间复杂度,DFS的时间复杂度为O(V+E),BFS的时间复杂度为O(V+E),其中V表示顶点数,E表示边数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值