/* 圖形的追蹤: 相鄰串列與廣度優先搜尋法(BFS) - 含權重顯示 */ #include #include #include #define MAX_V 100 /*最大節點數*/ #define TRUE 1 #define FALSE 0 /*定義資料結構*/ typedef struct node_tag { int vertex; struct node_tag *link; } Node; /*定義佇列結構*/ typedef struct { int items[MAX_V]; int front; int rear; } Queue; Node *adjlist[MAX_V+1]; /*宣告相鄰串列*/ int visited[MAX_V+1]; /*記錄頂點是否已拜訪*/ int total_vertex; int weight_matrix[MAX_V+1][MAX_V+1]; /* 儲存權重矩陣 */ void build_adjlist(void); void show_adjlist(void); void show_weight_matrix(void); void bfs(int); Node *searchlast(Node *); /*佇列操作函數*/ Queue* createQueue() { Queue *q = (Queue*)malloc(sizeof(Queue)); q->front = -1; q->rear = -1; return q; } int isEmpty(Queue* q) { return q->front == -1; } void enqueue(Queue* q, int value) { if(q->front == -1) q->front = 0; q->rear++; q->items[q->rear] = value; } int dequeue(Queue* q) { int item = q->items[q->front]; if(q->front == q->rear) { q->front = -1; q->rear = -1; } else { q->front++; } return item; } int main() { build_adjlist(); /*以相鄰串列表示圖形*/ show_weight_matrix(); /*顯示權重矩陣*/ show_adjlist(); /*顯示串列之資料*/ puts("\n------Breadth First Search------"); bfs(1); /*圖形之廣度優先搜尋,以頂點1為啟始頂點*/ printf("\n"); return 0; } void build_adjlist() { FILE *fptr; Node *node, *lastnode; int vi, vj; char line[256]; int weight; int line_count = 0; fptr = fopen("down_1.dat", "r"); if (fptr == NULL) { perror("down_1.dat"); exit(0); } // 計算總頂點數 while (fgets(line, sizeof(line), fptr)) { line_count++; } total_vertex = line_count; // 修改:移除減1 rewind(fptr); // 初始化權重矩陣為0 for(int i = 0; i <= total_vertex; i++) for(int j = 0; j <= total_vertex; j++) weight_matrix[i][j] = 0; // 初始化相鄰串列 for (vi = 1; vi <= total_vertex; vi++) { visited[vi] = FALSE; adjlist[vi] = (Node *)malloc(sizeof(Node)); adjlist[vi]->vertex = vi; adjlist[vi]->link = NULL; } // 讀取下三角形矩陣 for (vi = 1; vi <= total_vertex; vi++) { // 修改:只讀取到第vi個元素(下三角部分) for (vj = 1; vj < vi; vj++) { if (fscanf(fptr, "%d", &weight) != 1) { printf("Error reading weight at vi=%d, vj=%d\n", vi, vj); continue; } // 儲存權重到矩陣 weight_matrix[vi][vj] = weight; weight_matrix[vj][vi] = weight; // 因為是無向圖,所以對稱儲存 // 若有相鄰關係(weight = 1),則建立連結 if (weight == 1) { // 加入 vi -> vj 的連結 node = (Node *)malloc(sizeof(Node)); node->vertex = vj; node->link = NULL; lastnode = searchlast(adjlist[vi]); lastnode->link = node; // 加入 vj -> vi 的連結(因為是無向圖) node = (Node *)malloc(sizeof(Node)); node->vertex = vi; node->link = NULL; lastnode = searchlast(adjlist[vj]); lastnode->link = node; } } // 讀取對角線元素(一定是0,可以跳過) fscanf(fptr, "%d", &weight); } fclose(fptr); } /* 修改顯示權重矩陣的函數,使其更清晰 */ void show_weight_matrix() { int i, j; printf("\n=== Weight Matrix ===\n"); printf(" "); for(j = 1; j <= total_vertex; j++) { printf("V%-3d", j); } printf("\n"); for(i = 1; i <= total_vertex; i++) { printf("V%-3d", i); for(j = 1; j <= total_vertex; j++) { printf("%-4d", weight_matrix[i][j]); } printf("\n"); } printf("\n"); } /*顯示各相鄰串列之資料*/ void show_adjlist() { int index; Node *ptr; puts("Head adjacency nodes"); puts("------------------------------"); for (index = 1; index <= total_vertex; index++) { printf("V%-2d ",adjlist[index]->vertex); ptr = adjlist[index]->link; while (ptr != NULL) { printf("--> V%d ",ptr->vertex); ptr = ptr->link; } printf("\n"); } } /*圖形之廣度優先搜尋*/ void bfs(int start) { Queue* q = createQueue(); Node* ptr; // 將起始節點加入佇列 enqueue(q, start); visited[start] = TRUE; while(!isEmpty(q)) { // 從佇列取出節點並印出 int currentVertex = dequeue(q); printf("V%d ", currentVertex); // 將所有相鄰且未拜訪的節點加入佇列,並按節點編號排序 int neighbors[MAX_V]; int neighborCount = 0; // 收集所有未訪問的相鄰節點 ptr = adjlist[currentVertex]->link; while(ptr != NULL) { if(!visited[ptr->vertex]) { neighbors[neighborCount++] = ptr->vertex; } ptr = ptr->link; } // 將相鄰節點按編號排序 for(int i = 0; i < neighborCount - 1; i++) { for(int j = 0; j < neighborCount - i - 1; j++) { if(neighbors[j] > neighbors[j + 1]) { int temp = neighbors[j]; neighbors[j] = neighbors[j + 1]; neighbors[j + 1] = temp; } } } // 按順序加入佇列 for(int i = 0; i < neighborCount; i++) { enqueue(q, neighbors[i]); visited[neighbors[i]] = TRUE; } } free(q); } /*搜尋串列最後節點函數*/ Node *searchlast(Node *linklist) { Node *ptr; ptr = linklist; while (ptr->link != NULL) ptr = ptr->link; return ptr; }