【數據結構】廣度優先搜索算法BFS

對于廣度優先遍歷算法DFS可以參考前一篇文章【數據結構】深度優先搜索算法DFS

廣度優先遍歷

廣度優先遍歷(Breadth_First_Search),又稱為廣度優先搜索,簡稱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

  • 圖的深度優先搜索算法和廣度優先搜索算法在時間復雜度上是一樣的。
  • 深度優先更適合目標比較明確,以找到目標為目的的情況。
  • 廣度優先更適合在不斷擴大遍歷范圍時找到相對最優解的情況。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容