// 鄰接矩陣的深度和廣度優先遍歷 #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; }