鄰接矩陣DFS,BFS代碼實現


// 鄰接矩陣的深度和廣度優先遍歷
#include <stdio.h>

#define OK 1      // 執行成功
#define ERROR 0   // 執行失敗
#define TRUE 1    // 返回值為真
#define FALSE 0   // 返回值為假

typedef int Status; // 執行狀態(OK、ERROR)
typedef int Boolean; // 布爾值(TRUE、FALSE)

typedef char VertexType; // 頂點元素類型
typedef int EdgeType; // 邊上權值的類型

#define MAXSIZE 9 // 隊列儲存空間初始分配量
#define MAXVEX 100 // 最大頂點數

// 鄰接矩陣結構(無向圖)
typedef struct {
    VertexType vexs[MAXVEX]; // 頂點表
    EdgeType arc[MAXVEX][MAXVEX]; // 邊表
    int numNodes, numEdges; // 圖的頂點數、邊數
} MGraph;

/************** 用到的隊列結構與函數 **************/

// 循環隊列順序存儲結構
typedef struct {
    int data[MAXSIZE]; // 用於存值的數組
    int front; // 頭指針
    int rear; // 尾指針,若隊列不空,指向隊尾元素的下一個位置
} Queue;

/**
 * 初始化一個空隊列
 * @param Q 隊列
 * @return 執行狀態
 */
Status InitQueue(Queue* Q) {
    Q->front = Q->rear = 0; // 隊頭和隊尾指針都指向0
    return OK;
}

/**
 * 判斷隊列是否為空
 * @param Q 隊列
 * @return 隊列是否為空
 */
Boolean QueueEmpty(Queue Q) {
    if (Q.front == Q.rear) { // 隊頭等於隊尾指針,隊列為空
        return TRUE;
    }
    else {
        return FALSE;
    }
}

/**
 * 將元素e插入隊列Q的隊尾
 * @param Q 隊列
 * @param e 插入的元素
 * @return 執行狀態
 */
Status EnQueue(Queue* Q, int e) {
    // 隊列已滿,插入失敗
    if ((Q->rear + 1) % MAXSIZE == Q->front) {
        return ERROR;
    }

    // 將元素e插入隊尾
    Q->data[Q->rear] = e;

    // 設置隊尾指針指向下一個位置,若到最后則轉向頭部
    Q->rear = (Q->rear + 1) % MAXSIZE;
    return OK;
}

/**
 * 隊頭元素出隊,用e返回其值
 * @param Q 隊列
 * @param e 隊頭元素的值
 * @return 執行狀態
 */
Status DeQueue(Queue* Q, int* e) {
    // 對頭指針等於對尾指針,此時隊列為空,出隊失敗
    if (Q->front == Q->rear) {
        return ERROR;
    }

    // 將隊頭元素的值賦給元素e
    *e = Q->data[Q->front];

    // 設置隊頭指針指向下一個位置,若到最后則轉向頭部
    Q->front = (Q->front + 1) % MAXSIZE;
    return OK;
}

/*************************************************/

/**
 * 生成鄰接矩陣
 * @param G 鄰接矩陣
 */
void CreateMGraph(MGraph* G) {
    int i, j; // 用於遍歷元素

    G->numEdges = 15; // 設置有15條邊
    G->numNodes = 6; // 設置有9個頂點

    // 讀入頂點信息,建立頂點表
    G->vexs[0] = 'A';
    G->vexs[1] = 'B';
    G->vexs[2] = 'C';
    G->vexs[3] = 'D';
    G->vexs[4] = 'E';
    G->vexs[5] = 'F';


    // 初始化圖的邊
    for (i = 0; i < G->numNodes; i++) {
        for (j = 0; j < G->numNodes; j++) {
            G->arc[i][j] = 0; // 設置所有邊的值都為0
        }
    }

    // 設置特定邊(如果arc[i][j] = 1,代表頂點i到頂點j有邊相連)
    G->arc[0][1] = 1;
    G->arc[0][2] = 1;
    G->arc[0][4] = 1;
    G->arc[1][0] = 1;
    G->arc[1][3] = 1;
    G->arc[1][4] = 1;
    G->arc[2][0] = 1;
    G->arc[2][4] = 1;
    G->arc[2][5] = 1;
    G->arc[3][1] = 1;
    G->arc[3][4] = 1;
    G->arc[3][5] = 1;
    G->arc[4][0] = 1;
    G->arc[4][1] = 1;
    G->arc[4][2] = 1;
    G->arc[4][3] = 1;
    G->arc[4][5] = 1;
    G->arc[5][2] = 1;
    G->arc[5][3] = 1;
    G->arc[5][4] = 1;

    // 設置對稱邊
    for (i = 0; i < G->numNodes; i++) {
        for (j = i; j < G->numNodes; j++) {
            G->arc[j][i] = G->arc[i][j];
        }
    }
}

// 訪問標志的數組
Boolean visited[MAXVEX];


/**
 * 鄰接矩陣的深度優先遞歸算法
 * @param G 鄰接矩陣
 * @param i 頂點下標
 */
void DFS(MGraph G, int i) {
    int j; // 用於遍歷元素

    visited[i] = TRUE; // 記錄該下標的元素已被訪問

    printf("%c ", G.vexs[i]); // 打印該位置的頂點值

    // 遍歷圖中的頂點
    for (j = 0; j < G.numNodes; j++) {
        // 頂點i到頂點j有邊相連,並且頂點j未被訪問過
        if (G.arc[i][j] == 1 && !visited[j]) {
            DFS(G, j); // 對頂點j進行訪問
        }
    }
}

/**
 * 鄰接矩陣的深度遍歷
 * @param G 鄰接矩陣
 */
void DFSTraverse(MGraph G) {
    int i; // 用於遍歷元素

    // 初始化設置所有頂點都沒被訪問過
    for (i = 0; i < G.numNodes; i++) {
        visited[i] = FALSE;
    }

    // 遍歷頂點i
    for (i = 0; i < G.numNodes; i++) {
        // 如果頂點i未被訪問過
        if (!visited[i]) {
            DFS(G, i); // 訪問頂點i
        }
    }
}

/**
 * 鄰接矩陣的廣度遍歷算法
 * @param G 鄰接矩陣
 */
void BFSTraverse(MGraph G) {
    int i, j; // 用於遍歷元素
    Queue Q; // 隊列

    // 初始設置圖的所有頂點都沒被訪問過
    for (i = 0; i < G.numNodes; i++) {
        visited[i] = FALSE;
    }

    InitQueue(&Q); // 初始化隊列

    // 對每一個頂點做循環
    for (i = 0; i < G.numNodes; i++) {
        if (!visited[i]) { // 該頂點未被訪問過,進行處理
            visited[i] = TRUE; // 設置該頂點i已被訪問

            printf("%c ", G.vexs[i]); // 打印該頂點i的值

            EnQueue(&Q, i); // 將該頂點i入隊

            // 當隊列非空時,進行循環
            while (!QueueEmpty(Q)) {
                DeQueue(&Q, &i); // 將隊頭元素出隊,賦值給i

                // 遍歷當前節點以外的節點j
                for (j = 0; j < G.numNodes; j++) {
                    // 若頂點j與當前節點存在邊,並且未被訪問過
                    if (G.arc[i][j] == 1 && !visited[j]) {
                        visited[j] = TRUE; // 設置頂點j已被訪問
                        printf("%c ", G.vexs[j]); // 打印頂點j的值

                        EnQueue(&Q, j); // 將頂點j入隊
                    }
                }
            }
        }
    }
}

int main() {
    MGraph G; // 鄰接矩陣
    CreateMGraph(&G); // 創建鄰接矩陣
    printf("深度遍歷:");
    DFSTraverse(G); // 深度遍歷鄰接矩陣

    printf("\n廣度遍歷:");
    BFSTraverse(G); // 廣度遍歷鄰接矩陣

    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM