|
| 1 | +/** |
| 2 | + * C: 邻接表表示的"有向图(List Directed Graph)" |
| 3 | + * |
| 4 | + * @author skywang |
| 5 | + * @date 2014/04/18 |
| 6 | + */ |
| 7 | + |
| 8 | +#include <stdio.h> |
| 9 | +#include <stdlib.h> |
| 10 | +#include <malloc.h> |
| 11 | +#include <string.h> |
| 12 | + |
| 13 | +#define MAX 100 |
| 14 | +#define isLetter(a) ((((a)>='a')&&((a)<='z')) || (((a)>='A')&&((a)<='Z'))) |
| 15 | +#define LENGTH(a) (sizeof(a)/sizeof(a[0])) |
| 16 | + |
| 17 | +// 邻接表中表对应的链表的顶点 |
| 18 | +typedef struct _ENode |
| 19 | +{ |
| 20 | + int ivex; // 该边所指向的顶点的位置 |
| 21 | + struct _ENode *next_edge; // 指向下一条弧的指针 |
| 22 | +}ENode, *PENode; |
| 23 | + |
| 24 | +// 邻接表中表的顶点 |
| 25 | +typedef struct _VNode |
| 26 | +{ |
| 27 | + char data; // 顶点信息 |
| 28 | + ENode *first_edge; // 指向第一条依附该顶点的弧 |
| 29 | +}VNode; |
| 30 | + |
| 31 | +// 邻接表 |
| 32 | +typedef struct _LGraph |
| 33 | +{ |
| 34 | + int vexnum; // 图的顶点的数目 |
| 35 | + int edgnum; // 图的边的数目 |
| 36 | + VNode vexs[MAX]; |
| 37 | +}LGraph; |
| 38 | + |
| 39 | +/* |
| 40 | + * 返回ch在matrix矩阵中的位置 |
| 41 | + */ |
| 42 | +static int get_position(LGraph g, char ch) |
| 43 | +{ |
| 44 | + int i; |
| 45 | + for(i=0; i<g.vexnum; i++) |
| 46 | + if(g.vexs[i].data==ch) |
| 47 | + return i; |
| 48 | + return -1; |
| 49 | +} |
| 50 | + |
| 51 | +/* |
| 52 | + * 读取一个输入字符 |
| 53 | + */ |
| 54 | +static char read_char() |
| 55 | +{ |
| 56 | + char ch; |
| 57 | + |
| 58 | + do { |
| 59 | + ch = getchar(); |
| 60 | + } while(!isLetter(ch)); |
| 61 | + |
| 62 | + return ch; |
| 63 | +} |
| 64 | + |
| 65 | +/* |
| 66 | + * 将node链接到list的末尾 |
| 67 | + */ |
| 68 | +static void link_last(ENode *list, ENode *node) |
| 69 | +{ |
| 70 | + ENode *p = list; |
| 71 | + |
| 72 | + while(p->next_edge) |
| 73 | + p = p->next_edge; |
| 74 | + p->next_edge = node; |
| 75 | +} |
| 76 | + |
| 77 | +/* |
| 78 | + * 创建邻接表对应的图(自己输入) |
| 79 | + */ |
| 80 | +LGraph* create_lgraph() |
| 81 | +{ |
| 82 | + char c1, c2; |
| 83 | + int v, e; |
| 84 | + int i, p1, p2; |
| 85 | + ENode *node1, *node2; |
| 86 | + LGraph* pG; |
| 87 | + |
| 88 | + // 输入"顶点数"和"边数" |
| 89 | + printf("input vertex number: "); |
| 90 | + scanf("%d", &v); |
| 91 | + printf("input edge number: "); |
| 92 | + scanf("%d", &e); |
| 93 | + if ( v < 1 || e < 1 || (e > (v * (v-1)))) |
| 94 | + { |
| 95 | + printf("input error: invalid parameters!\n"); |
| 96 | + return NULL; |
| 97 | + } |
| 98 | + |
| 99 | + if ((pG=(LGraph*)malloc(sizeof(LGraph))) == NULL ) |
| 100 | + return NULL; |
| 101 | + memset(pG, 0, sizeof(LGraph)); |
| 102 | + |
| 103 | + // 初始化"顶点数"和"边数" |
| 104 | + pG->vexnum = v; |
| 105 | + pG->edgnum = e; |
| 106 | + // 初始化"邻接表"的顶点 |
| 107 | + for(i=0; i<pG->vexnum; i++) |
| 108 | + { |
| 109 | + printf("vertex(%d): ", i); |
| 110 | + pG->vexs[i].data = read_char(); |
| 111 | + pG->vexs[i].first_edge = NULL; |
| 112 | + } |
| 113 | + |
| 114 | + // 初始化"邻接表"的边 |
| 115 | + for(i=0; i<pG->edgnum; i++) |
| 116 | + { |
| 117 | + // 读取边的起始顶点和结束顶点 |
| 118 | + printf("edge(%d): ", i); |
| 119 | + c1 = read_char(); |
| 120 | + c2 = read_char(); |
| 121 | + |
| 122 | + p1 = get_position(*pG, c1); |
| 123 | + p2 = get_position(*pG, c2); |
| 124 | + // 初始化node1 |
| 125 | + node1 = (ENode*)malloc(sizeof(ENode)); |
| 126 | + node1->ivex = p2; |
| 127 | + // 将node1链接到"p1所在链表的末尾" |
| 128 | + if(pG->vexs[p1].first_edge == NULL) |
| 129 | + pG->vexs[p1].first_edge = node1; |
| 130 | + else |
| 131 | + link_last(pG->vexs[p1].first_edge, node1); |
| 132 | + } |
| 133 | + |
| 134 | + return pG; |
| 135 | +} |
| 136 | + |
| 137 | +/* |
| 138 | + * 创建邻接表对应的图(用已提供的数据) |
| 139 | + */ |
| 140 | +LGraph* create_example_lgraph() |
| 141 | +{ |
| 142 | + char c1, c2; |
| 143 | + char vexs[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G'}; |
| 144 | + char edges[][2] = { |
| 145 | + {'A', 'B'}, |
| 146 | + {'B', 'C'}, |
| 147 | + {'B', 'E'}, |
| 148 | + {'B', 'F'}, |
| 149 | + {'C', 'E'}, |
| 150 | + {'D', 'C'}, |
| 151 | + {'E', 'B'}, |
| 152 | + {'E', 'D'}, |
| 153 | + {'F', 'G'}}; |
| 154 | + int vlen = LENGTH(vexs); |
| 155 | + int elen = LENGTH(edges); |
| 156 | + int i, p1, p2; |
| 157 | + ENode *node1, *node2; |
| 158 | + LGraph* pG; |
| 159 | + |
| 160 | + |
| 161 | + if ((pG=(LGraph*)malloc(sizeof(LGraph))) == NULL ) |
| 162 | + return NULL; |
| 163 | + memset(pG, 0, sizeof(LGraph)); |
| 164 | + |
| 165 | + // 初始化"顶点数"和"边数" |
| 166 | + pG->vexnum = vlen; |
| 167 | + pG->edgnum = elen; |
| 168 | + // 初始化"邻接表"的顶点 |
| 169 | + for(i=0; i<pG->vexnum; i++) |
| 170 | + { |
| 171 | + pG->vexs[i].data = vexs[i]; |
| 172 | + pG->vexs[i].first_edge = NULL; |
| 173 | + } |
| 174 | + |
| 175 | + // 初始化"邻接表"的边 |
| 176 | + for(i=0; i<pG->edgnum; i++) |
| 177 | + { |
| 178 | + // 读取边的起始顶点和结束顶点 |
| 179 | + c1 = edges[i][0]; |
| 180 | + c2 = edges[i][1]; |
| 181 | + |
| 182 | + p1 = get_position(*pG, c1); |
| 183 | + p2 = get_position(*pG, c2); |
| 184 | + // 初始化node1 |
| 185 | + node1 = (ENode*)malloc(sizeof(ENode)); |
| 186 | + node1->ivex = p2; |
| 187 | + // 将node1链接到"p1所在链表的末尾" |
| 188 | + if(pG->vexs[p1].first_edge == NULL) |
| 189 | + pG->vexs[p1].first_edge = node1; |
| 190 | + else |
| 191 | + link_last(pG->vexs[p1].first_edge, node1); |
| 192 | + } |
| 193 | + |
| 194 | + return pG; |
| 195 | +} |
| 196 | + |
| 197 | +/* |
| 198 | + * 深度优先搜索遍历图的递归实现 |
| 199 | + */ |
| 200 | +static void DFS(LGraph G, int i, int *visited) |
| 201 | +{ |
| 202 | + int w; |
| 203 | + ENode *node; |
| 204 | + |
| 205 | + visited[i] = 1; |
| 206 | + printf("%c ", G.vexs[i].data); |
| 207 | + node = G.vexs[i].first_edge; |
| 208 | + while (node != NULL) |
| 209 | + { |
| 210 | + if (!visited[node->ivex]) |
| 211 | + DFS(G, node->ivex, visited); |
| 212 | + node = node->next_edge; |
| 213 | + } |
| 214 | +} |
| 215 | + |
| 216 | +/* |
| 217 | + * 深度优先搜索遍历图 |
| 218 | + */ |
| 219 | +void DFSTraverse(LGraph G) |
| 220 | +{ |
| 221 | + int i; |
| 222 | + int visited[MAX]; // 顶点访问标记 |
| 223 | + |
| 224 | + // 初始化所有顶点都没有被访问 |
| 225 | + for (i = 0; i < G.vexnum; i++) |
| 226 | + visited[i] = 0; |
| 227 | + |
| 228 | + printf("DFS: "); |
| 229 | + for (i = 0; i < G.vexnum; i++) |
| 230 | + { |
| 231 | + if (!visited[i]) |
| 232 | + DFS(G, i, visited); |
| 233 | + } |
| 234 | + printf("\n"); |
| 235 | +} |
| 236 | + |
| 237 | +/* |
| 238 | + * 广度优先搜索(类似于树的层次遍历) |
| 239 | + */ |
| 240 | +void BFS(LGraph G) |
| 241 | +{ |
| 242 | + int head = 0; |
| 243 | + int rear = 0; |
| 244 | + int queue[MAX]; // 辅组队列 |
| 245 | + int visited[MAX]; // 顶点访问标记 |
| 246 | + int i, j, k; |
| 247 | + ENode *node; |
| 248 | + |
| 249 | + for (i = 0; i < G.vexnum; i++) |
| 250 | + visited[i] = 0; |
| 251 | + |
| 252 | + printf("BFS: "); |
| 253 | + for (i = 0; i < G.vexnum; i++) |
| 254 | + { |
| 255 | + if (!visited[i]) |
| 256 | + { |
| 257 | + visited[i] = 1; |
| 258 | + printf("%c ", G.vexs[i].data); |
| 259 | + queue[rear++] = i; // 入队列 |
| 260 | + } |
| 261 | + while (head != rear) |
| 262 | + { |
| 263 | + j = queue[head++]; // 出队列 |
| 264 | + node = G.vexs[j].first_edge; |
| 265 | + while (node != NULL) |
| 266 | + { |
| 267 | + k = node->ivex; |
| 268 | + if (!visited[k]) |
| 269 | + { |
| 270 | + visited[k] = 1; |
| 271 | + printf("%c ", G.vexs[k].data); |
| 272 | + queue[rear++] = k; |
| 273 | + } |
| 274 | + node = node->next_edge; |
| 275 | + } |
| 276 | + } |
| 277 | + } |
| 278 | + printf("\n"); |
| 279 | +} |
| 280 | + |
| 281 | +/* |
| 282 | + * 打印邻接表图 |
| 283 | + */ |
| 284 | +void print_lgraph(LGraph G) |
| 285 | +{ |
| 286 | + int i,j; |
| 287 | + ENode *node; |
| 288 | + |
| 289 | + printf("List Graph:\n"); |
| 290 | + for (i = 0; i < G.vexnum; i++) |
| 291 | + { |
| 292 | + printf("%d(%c): ", i, G.vexs[i].data); |
| 293 | + node = G.vexs[i].first_edge; |
| 294 | + while (node != NULL) |
| 295 | + { |
| 296 | + printf("%d(%c) ", node->ivex, G.vexs[node->ivex].data); |
| 297 | + node = node->next_edge; |
| 298 | + } |
| 299 | + printf("\n"); |
| 300 | + } |
| 301 | +} |
| 302 | + |
| 303 | +void main() |
| 304 | +{ |
| 305 | + LGraph* pG; |
| 306 | + |
| 307 | + // 自定义"图"(自己输入数据) |
| 308 | + //pG = create_lgraph(); |
| 309 | + // 采用已有的"图" |
| 310 | + pG = create_example_lgraph(); |
| 311 | + |
| 312 | + // 打印图 |
| 313 | + print_lgraph(*pG); |
| 314 | + DFSTraverse(*pG); |
| 315 | + BFS(*pG); |
| 316 | +} |
0 commit comments