1. 程式人生 > >C語言鄰接表實現圖的任意兩點間所有路徑

C語言鄰接表實現圖的任意兩點間所有路徑

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DEBUG 1
#if DEBUG
#define PRINTF printf
#else
#define PRINTF
#endif

//最大節點個數
#define MAX_VEX (256)
//標記節點是否被訪問過(被加入路徑)
char visited[MAX_VEX+1];
//記錄各節點在路徑中的下一節點
char path_next[MAX_VEX];
//使用陣列實現棧的功能,用於記錄當前走的路徑
int path_record[MAX_VEX];
//表示path_record陣列最大索引,來標識當前的棧頂位置
int g_idx; //邊 typedef struct edge_node { int idx; struct edge_node *next; }edge_node_t; //節點 typedef struct vertex_node { char data; edge_node_t *first_edge; }vertex_node_t, vertex_node_list[MAX_VEX]; //圖 typedef struct graph { vertex_node_list list; int num_vex; int num_edge; }graph_t; void
print_graph(graph_t *g) { int i; edge_node_t *p; for(i=0; i<g->num_vex; i++) { printf("<%d> : %c ", i, g->list[i].data); if(NULL == g->list[i].first_edge) printf(" >> NULL"); else { for(p=g->list[i].first_edge; p!=NULL; p=p->next) { printf
(" >> <%d> %c", p->idx, g->list[p->idx].data); } } printf("\n"); } } void free_graph(graph_t *g) { int i; edge_node_t *p, *q; for(i=0; i<g->num_vex; i++) { p = g->list[i].first_edge; while(p) { q = p->next; free(p); p = q; } } } int create_graph(graph_t *g) { int i, j, k; edge_node_t *p, *q; int ret; //輸入節點數和邊數 PRINTF("input num of vertex and num of edge : "); ret = scanf("%d %d\n", &(g->num_vex), &(g->num_edge)); PRINTF("ret = %d, num_vex : %d, num_edge : %d\n", ret, g->num_vex, g->num_edge); //輸入節點資訊 PRINTF("input data of vertex:\n"); for(i=0; i<g->num_vex; i++) { PRINTF("vertex %d : ", i+1); ret = scanf("%c\n", &(g->list[i].data)); PRINTF("ret = %d, %d : %d\n", ret, i, g->list[i].data); g->list[i].first_edge = NULL; } //輸入邊資訊;當前實現按照無向圖建立 for(k=0; k<g->num_edge; k++) { PRINTF("input the index of (vi, vj) : "); ret = scanf("%d %d\n", &i, &j); PRINTF("ret : %d, i : %d, j : %d\n", ret, i, j); p = (edge_node_t *)malloc(sizeof(edge_node_t)); memset(p, 0x0, sizeof(edge_node_t)); p->idx = j; #if 0 p->next = g->list[i].first_edge; g->list[i].first_edge = p; #else if(g->list[i].first_edge == NULL) g->list[i].first_edge = p; else { for(q=g->list[i].first_edge; q->next!=NULL; q=q->next); q->next = p; } #endif p = (edge_node_t *)malloc(sizeof(edge_node_t)); memset(p, 0x0, sizeof(edge_node_t)); p->idx = i; #if 0 p->next = g->list[j].first_edge; g->list[j].first_edge = p; #else if(g->list[j].first_edge == NULL) g->list[j].first_edge = p; else { for(q=g->list[j].first_edge; q->next!=NULL; q=q->next); q->next = p; } #endif } } //查詢與當前節點連線的下一個可用的節點 edge_node_t *neighbour(graph_t *g, int idx) { edge_node_t *p; p = g->list[idx].first_edge; while(NULL != p) { if(visited[p->idx] == 1)//已在路徑中 { p = p->next; } else { if(-1 == path_next[idx])//未被路徑訪問過 { while(p!=NULL && visited[p->idx]==1) p = p->next; return p; } else if(p->idx == path_next[idx])//被上一次路徑訪問過 { p = p->next; while(p!=NULL && visited[p->idx]==1) p = p->next; return p; } else//被以前的路徑訪問過 { p = p->next; } } } } /***************************************************************************** 函 數 名 : all_path 功能描述 : 在圖g中查詢起始節點start到結束節點end之間的所有路徑並輸出 輸入引數 : graph_t *g 圖的鄰接表儲存結構 int start 起始節點 int end 結束節點 輸出引數 : 無 返 回 值 : *****************************************************************************/ void all_path(graph_t *g, int start, int end) { int i, cur_vex; edge_node_t *p; while(g_idx >= 0) { cur_vex = path_record[g_idx]; if(cur_vex == end)//已走到結束節點,輸出完整路徑 { PRINTF("%d -> %d : ", start, end); for(i=0; i<=g_idx; i++) { if(i == 0) PRINTF("<%d> %c", path_record[i], g->list[path_record[i]].data); else PRINTF(" >> <%d> %c", path_record[i], g->list[path_record[i]].data); } PRINTF("\n"); //結束節點出棧 visited[end] = 0; path_record[g_idx] = -1; path_next[end] = -1; g_idx--; } else { p = neighbour(g, cur_vex); if(p != NULL) { //有可走的路徑下一跳,當前節點入棧 path_next[cur_vex] = p->idx; g_idx++; path_record[g_idx] = p->idx; visited[p->idx] = 1; } else { //沒有可走的路徑下一跳,當前節點出棧 visited[cur_vex] = 0; path_record[g_idx] = -1; path_next[cur_vex] = -1; g_idx--; } } } } int main() { graph_t g; int start, end; int ret, i; memset(&g, 0x0, sizeof(g)); #if DEBUG freopen("data.txt", "r", stdin); #endif create_graph(&g); #if DEBUG PRINTF("[%s][%d] print_graph : \n", __FUNCTION__, __LINE__); print_graph(&g); #endif //初始化 for(i=0; i<g.num_vex; i++) { visited[i] = 0; path_next[i] = -1; path_record[i] = -1; } g_idx = 0; //輸入起始和結束節點 PRINTF("input start and end node index : "); ret = scanf("%d %d\n", &start, &end); PRINTF("ret : %d, start : %d, end : %d\n", ret, start, end); //起始節點入棧 path_record[g_idx] = start; visited[start] = 1; all_path(&g, start, end); free_graph(&g); return 0; } // 樣例輸入: /* 8 9 a b c d e f g h 0 1 0 2 1 3 1 4 3 7 4 7 2 5 2 6 5 6 3 6 */ /* 8 9 0 1 2 3 4 5 6 7 0 1 0 2 1 3 1 4 3 7 4 7 2 5 2 6 5 6 3 6 */ /* 9 11 0 1 2 3 4 5 6 7 8 0 1 0 2 1 3 1 4 3 7 4 7 2 5 2 6 5 6 5 8 6 8 3 6 */