【数据结构】广度优先搜索算法BFS

对于广度优先遍历算法DFS可以参考前一篇文章【数据结构】深度优先搜索算法DFS

广度优先遍历

广度优先遍历(Breadth_First_Search),又称为广度优先搜索,简称BFS。

图的BFS类似于树的层序遍历。

《【数据结构】广度优先搜索算法BFS》 广度优先遍历

  • 如图将左边的图变形,得到右边的图,然后一层一层的遍历。
  • 这里借助一个队列来实现一层一层的遍历。

邻接矩阵的BFS

核心代码

/**
 * 邻接矩阵的广度优先遍历算法
 */
void BFSTraverse(MGraph G){
    
    int i,j;
    Queue Q;
    
    for (i = 0; i < G.numVertexes; i++) {
        visited[i] = FALSE;
    }
    
    InitQueue(&Q);  // 初始化辅助队列
    
    for (i = 0; i < G.numVertexes; i++) {  // 对每个顶点做循环
        
        if (!visited[i]) {
            
            visited[i] = TRUE;
            printf("%c", G.vexs[i]);
            EnQueue(&Q, i);  // 顶点入队列
            
            while (!QueueEmpty(Q)) {  // 队列不为空
                DeQueue(&Q, &i);  // 将队列元素出队列
                
                for (j = 0; j < G.numVertexes; j++) {
                    if (G.arc[i][j] == 1 && !visited[j]) {  // 判断其他顶点若与当前顶点存在边且未访问过
                        visited[j] = TRUE;
                        printf("%c", G.vexs[j]);
                        EnQueue(&Q, j);
                    }
                }
            }
        }
    }
}

附上队列操作的代码

#pragma 用到的队列
//循环队列的存储结构
typedef struct {
    int data[MAXSIZE];
    int front;  // 头指针
    int rear;   // 尾指针,若队列不为空,指向队列尾元素的下一个位置
}Queue;

/**
 * 初始化一个空队列
 */
Status InitQueue(Queue *Q){
    Q->front = 0;
    Q->rear = 0;
    return OK;
}

/**
 * 判断队列是否为空
 */
Status QueueEmpty(Queue Q){
    if (Q.front == Q.rear)
        return TRUE;
    else
        return FALSE;
}

/**
 * 插入
 */
Status EnQueue(Queue * Q, int e){
    if ((Q->rear + 1) % MAXSIZE == Q->front)  // 队列满
        return ERROR;
    
    Q->data[Q->rear] = e;             // 元素e赋值给对尾
    Q->rear = (Q->rear + 1)% MAXSIZE;  // rear指针后移一个位置
    
    return OK;
}

/**
 * 删除队列中的元素
 */
Status DeQueue(Queue * Q, int *e){
    
    if (Q->front == Q->rear)
        return ERROR;
    *e = Q->data[Q->front];  // 将队头元素赋值给e
    Q->front = (Q->front+1)%MAXSIZE;  // front指针后移
    
    return OK;
}

邻接表的BFS

核心代码

void BFSTraverse(GraphAdjList GL){
    
    int i;
    EdgeNode *p;
    
    Queue Q;
    
    for (i = 0; i < GL->numVertexes; i++)
        visited[i] = FALSE;
    
    InitQueue(&Q);
    
    for (i = 0; i < GL->numVertexes; i++) {
        
        if (!visited[i]) {
            
            visited[i] = TRUE;
            printf("%c", GL->adjList[i].data);  // 打印顶点
            
            EnQueue(&Q, i);
            
            while (!QueueEmpty(Q)) {
                
                DeQueue(&Q, &i);
                
                p = GL->adjList[i].firstedge;  // 找到当前顶点的边表链表头指针
                
                while (p) {
                    if (!visited[p->adjvex]) {  // 若次顶点没有被访问过
                        
                        visited[p->adjvex] = TRUE;
                        printf("%c", GL->adjList[p->adjvex].data);
                        EnQueue(&Q, p->adjvex);   // 将次顶点入队列
                        
                    }
                    p = p->next;
                }
            }
        }
    }
}

图的DFS与BFS

  • 图的深度优先搜索算法和广度优先搜索算法在时间复杂度上是一样的。
  • 深度优先更适合目标比较明确,以找到目标为目的的情况。
  • 广度优先更适合在不断扩大遍历范围时找到相对最优解的情况。
    原文作者:STzen
    原文地址: https://www.jianshu.com/p/e58665864d54
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞