鱼C论坛

 找回密码
 立即注册
查看: 5843|回复: 8

[技术交流] 图的遍历完整代码(邻接表)

[复制链接]
发表于 2016-3-9 02:10:01 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 小甲鱼的二师兄 于 2016-3-9 14:57 编辑

邻接表(无向图)

  1. /**
  2. * C: 邻接表表示的"无向图(List Undirected Graph)"
  3. */

  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <malloc.h>
  7. #include <string.h>

  8. #define MAX 100
  9. #define isLetter(a)  ((((a)>='a')&&((a)<='z')) || (((a)>='A')&&((a)<='Z')))
  10. #define LENGTH(a)  (sizeof(a)/sizeof(a[0]))

  11. // 邻接表中表对应的链表的顶点
  12. typedef struct _ENode
  13. {
  14.     int ivex;                   // 该边所指向的顶点的位置
  15.     struct _ENode *next_edge;   // 指向下一条弧的指针
  16. }ENode, *PENode;

  17. // 邻接表中表的顶点
  18. typedef struct _VNode
  19. {
  20.     char data;              // 顶点信息
  21.     ENode *first_edge;      // 指向第一条依附该顶点的弧
  22. }VNode;

  23. // 邻接表
  24. typedef struct _LGraph
  25. {
  26.     int vexnum;             // 图的顶点的数目
  27.     int edgnum;             // 图的边的数目
  28.     VNode vexs[MAX];
  29. }LGraph;

  30. /*
  31. * 返回ch在matrix矩阵中的位置
  32. */
  33. static int get_position(LGraph g, char ch)
  34. {
  35.     int i;
  36.     for(i=0; i<g.vexnum; i++)
  37.         if(g.vexs[i].data==ch)
  38.             return i;
  39.     return -1;
  40. }

  41. /*
  42. * 读取一个输入字符
  43. */
  44. static char read_char()
  45. {
  46.     char ch;

  47.     do {
  48.         ch = getchar();
  49.     } while(!isLetter(ch));

  50.     return ch;
  51. }

  52. /*
  53. * 将node链接到list的末尾
  54. */
  55. static void link_last(ENode *list, ENode *node)
  56. {
  57.     ENode *p = list;

  58.     while(p->next_edge)
  59.         p = p->next_edge;
  60.     p->next_edge = node;
  61. }

  62. /*
  63. * 创建邻接表对应的图(自己输入)
  64. */
  65. LGraph* create_lgraph()
  66. {
  67.     char c1, c2;
  68.     int v, e;
  69.     int i, p1, p2;
  70.     ENode *node1, *node2;
  71.     LGraph* pG;

  72.     // 输入"顶点数"和"边数"
  73.     printf("input vertex number: ");
  74.     scanf("%d", &v);
  75.     printf("input edge number: ");
  76.     scanf("%d", &e);
  77.     if ( v < 1 || e < 1 || (e > (v * (v-1))))
  78.     {
  79.         printf("input error: invalid parameters!\n");
  80.         return NULL;
  81.     }

  82.     if ((pG=(LGraph*)malloc(sizeof(LGraph))) == NULL )
  83.         return NULL;
  84.     memset(pG, 0, sizeof(LGraph));

  85.     // 初始化"顶点数"和"边数"
  86.     pG->vexnum = v;
  87.     pG->edgnum = e;
  88.     // 初始化"邻接表"的顶点
  89.     for(i=0; i<pG->vexnum; i++)
  90.     {
  91.         printf("vertex(%d): ", i);
  92.         pG->vexs[i].data = read_char();
  93.         pG->vexs[i].first_edge = NULL;
  94.     }

  95.     // 初始化"邻接表"的边
  96.     for(i=0; i<pG->edgnum; i++)
  97.     {
  98.         // 读取边的起始顶点和结束顶点
  99.         printf("edge(%d): ", i);
  100.         c1 = read_char();
  101.         c2 = read_char();

  102.         p1 = get_position(*pG, c1);
  103.         p2 = get_position(*pG, c2);

  104.         // 初始化node1
  105.         node1 = (ENode*)malloc(sizeof(ENode));
  106.         node1->ivex = p2;
  107.         node1->next_edge = NULL;
  108.         // 将node1链接到"p1所在链表的末尾"
  109.         if(pG->vexs[p1].first_edge == NULL)
  110.           pG->vexs[p1].first_edge = node1;
  111.         else
  112.             link_last(pG->vexs[p1].first_edge, node1);
  113.         // 初始化node2
  114.         node2 = (ENode*)malloc(sizeof(ENode));
  115.         node2->ivex = p1;
  116.         node1->next_edge = NULL;
  117.         // 将node2链接到"p2所在链表的末尾"
  118.         if(pG->vexs[p2].first_edge == NULL)
  119.           pG->vexs[p2].first_edge = node2;
  120.         else
  121.             link_last(pG->vexs[p2].first_edge, node2);
  122.     }

  123.     return pG;
  124. }

  125. /*
  126. * 创建邻接表对应的图(用已提供的数据)
  127. */
  128. LGraph* create_example_lgraph()
  129. {
  130.     char c1, c2;
  131.     char vexs[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
  132.     char edges[][2] = {
  133.         {'A', 'C'},
  134.         {'A', 'D'},
  135.         {'A', 'F'},
  136.         {'B', 'C'},
  137.         {'C', 'D'},
  138.         {'E', 'G'},
  139.         {'F', 'G'}};
  140.     int vlen = LENGTH(vexs);
  141.     int elen = LENGTH(edges);
  142.     int i, p1, p2;
  143.     ENode *node1, *node2;
  144.     LGraph* pG;


  145.     if ((pG=(LGraph*)malloc(sizeof(LGraph))) == NULL )
  146.         return NULL;
  147.     memset(pG, 0, sizeof(LGraph));

  148.     // 初始化"顶点数"和"边数"
  149.     pG->vexnum = vlen;
  150.     pG->edgnum = elen;
  151.     // 初始化"邻接表"的顶点
  152.     for(i=0; i<pG->vexnum; i++)
  153.     {
  154.         pG->vexs[i].data = vexs[i];
  155.         pG->vexs[i].first_edge = NULL;
  156.     }

  157.     // 初始化"邻接表"的边
  158.     for(i=0; i<pG->edgnum; i++)
  159.     {
  160.         // 读取边的起始顶点和结束顶点
  161.         c1 = edges[i][0];
  162.         c2 = edges[i][1];

  163.         p1 = get_position(*pG, c1);
  164.         p2 = get_position(*pG, c2);

  165.         // 初始化node1
  166.         node1 = (ENode*)malloc(sizeof(ENode));
  167.         node1->ivex = p2;
  168.         node1->next_edge = NULL;
  169.         // 将node1链接到"p1所在链表的末尾"
  170.         if(pG->vexs[p1].first_edge == NULL)
  171.           pG->vexs[p1].first_edge = node1;
  172.         else
  173.             link_last(pG->vexs[p1].first_edge, node1);
  174.         // 初始化node2
  175.         node2 = (ENode*)malloc(sizeof(ENode));
  176.         node2->ivex = p1;
  177.         node2->next_edge = NULL;
  178.         // 将node2链接到"p2所在链表的末尾"
  179.         if(pG->vexs[p2].first_edge == NULL)
  180.           pG->vexs[p2].first_edge = node2;
  181.         else
  182.             link_last(pG->vexs[p2].first_edge, node2);
  183.     }

  184.     return pG;
  185. }

  186. /*
  187. * 深度优先搜索遍历图的递归实现
  188. */
  189. static void DFS(LGraph G, int i, int *visited)
  190. {
  191.     int w;
  192.     ENode *node;

  193.     visited[i] = 1;
  194.     printf("%c ", G.vexs[i].data);
  195.     node = G.vexs[i].first_edge;
  196.     while (node != NULL)
  197.     {
  198.         if (!visited[node->ivex])
  199.             DFS(G, node->ivex, visited);
  200.         node = node->next_edge;
  201.     }
  202. }

  203. /*
  204. * 深度优先搜索遍历图
  205. */
  206. void DFSTraverse(LGraph G)
  207. {
  208.     int i;
  209.     int visited[MAX];       // 顶点访问标记

  210.     // 初始化所有顶点都没有被访问
  211.     for (i = 0; i < G.vexnum; i++)
  212.         visited[i] = 0;

  213.     printf("DFS: ");
  214.     for (i = 0; i < G.vexnum; i++)
  215.     {
  216.         if (!visited[i])
  217.             DFS(G, i, visited);
  218.     }
  219.     printf("\n");
  220. }

  221. /*
  222. * 广度优先搜索(类似于树的层次遍历)
  223. */
  224. void BFS(LGraph G)
  225. {
  226.     int head = 0;
  227.     int rear = 0;
  228.     int queue[MAX];     // 辅组队列
  229.     int visited[MAX];   // 顶点访问标记
  230.     int i, j, k;
  231.     ENode *node;

  232.     for (i = 0; i < G.vexnum; i++)
  233.         visited[i] = 0;

  234.     printf("BFS: ");
  235.     for (i = 0; i < G.vexnum; i++)
  236.     {
  237.         if (!visited[i])
  238.         {
  239.             visited[i] = 1;
  240.             printf("%c ", G.vexs[i].data);
  241.             queue[rear++] = i;  // 入队列
  242.         }
  243.         while (head != rear)
  244.         {
  245.             j = queue[head++];  // 出队列
  246.             node = G.vexs[j].first_edge;
  247.             while (node != NULL)
  248.             {
  249.                 k = node->ivex;
  250.                 if (!visited[k])
  251.                 {
  252.                     visited[k] = 1;
  253.                     printf("%c ", G.vexs[k].data);
  254.                     queue[rear++] = k;
  255.                 }
  256.                 node = node->next_edge;
  257.             }
  258.         }
  259.     }
  260.     printf("\n");
  261. }

  262. /*
  263. * 打印邻接表图
  264. */
  265. void print_lgraph(LGraph G)
  266. {
  267.     int i,j;
  268.     ENode *node;

  269.     printf("List Graph:\n");
  270.     for (i = 0; i < G.vexnum; i++)
  271.     {
  272.         printf("%d(%c): ", i, G.vexs[i].data);
  273.         node = G.vexs[i].first_edge;
  274.         while (node != NULL)
  275.         {
  276.             printf("%d(%c) ", node->ivex, G.vexs[node->ivex].data);
  277.             node = node->next_edge;
  278.         }
  279.         printf("\n");
  280.     }
  281. }

  282. void main()
  283. {
  284.     LGraph* pG;

  285.     // 自定义"图"(自己输入数据)
  286.     //pG = create_lgraph();
  287.     // 采用已有的"图"
  288.     pG = create_example_lgraph();

  289.     // 打印图
  290.     print_lgraph(*pG);
  291.     DFSTraverse(*pG);
  292.     BFS(*pG);
  293. }
复制代码


邻接表(有向图)

  1. /**
  2. * C: 邻接表表示的"有向图(List Directed Graph)"
  3. */

  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <malloc.h>
  7. #include <string.h>

  8. #define MAX 100
  9. #define isLetter(a)  ((((a)>='a')&&((a)<='z')) || (((a)>='A')&&((a)<='Z')))
  10. #define LENGTH(a)  (sizeof(a)/sizeof(a[0]))

  11. // 邻接表中表对应的链表的顶点
  12. typedef struct _ENode
  13. {
  14.     int ivex;                   // 该边所指向的顶点的位置
  15.     struct _ENode *next_edge;   // 指向下一条弧的指针
  16. }ENode, *PENode;

  17. // 邻接表中表的顶点
  18. typedef struct _VNode
  19. {
  20.     char data;              // 顶点信息
  21.     ENode *first_edge;      // 指向第一条依附该顶点的弧
  22. }VNode;

  23. // 邻接表
  24. typedef struct _LGraph
  25. {
  26.     int vexnum;             // 图的顶点的数目
  27.     int edgnum;             // 图的边的数目
  28.     VNode vexs[MAX];
  29. }LGraph;

  30. /*
  31. * 返回ch在matrix矩阵中的位置
  32. */
  33. static int get_position(LGraph g, char ch)
  34. {
  35.     int i;
  36.     for(i=0; i<g.vexnum; i++)
  37.         if(g.vexs[i].data==ch)
  38.             return i;
  39.     return -1;
  40. }

  41. /*
  42. * 读取一个输入字符
  43. */
  44. static char read_char()
  45. {
  46.     char ch;

  47.     do {
  48.         ch = getchar();
  49.     } while(!isLetter(ch));

  50.     return ch;
  51. }

  52. /*
  53. * 将node链接到list的末尾
  54. */
  55. static void link_last(ENode *list, ENode *node)
  56. {
  57.     ENode *p = list;

  58.     while(p->next_edge)
  59.         p = p->next_edge;
  60.     p->next_edge = node;
  61. }

  62. /*
  63. * 创建邻接表对应的图(自己输入)
  64. */
  65. LGraph* create_lgraph()
  66. {
  67.     char c1, c2;
  68.     int v, e;
  69.     int i, p1, p2;
  70.     ENode *node1, *node2;
  71.     LGraph* pG;

  72.     // 输入"顶点数"和"边数"
  73.     printf("input vertex number: ");
  74.     scanf("%d", &v);
  75.     printf("input edge number: ");
  76.     scanf("%d", &e);
  77.     if ( v < 1 || e < 1 || (e > (v * (v-1))))
  78.     {
  79.         printf("input error: invalid parameters!\n");
  80.         return NULL;
  81.     }

  82.     if ((pG=(LGraph*)malloc(sizeof(LGraph))) == NULL )
  83.         return NULL;
  84.     memset(pG, 0, sizeof(LGraph));

  85.     // 初始化"顶点数"和"边数"
  86.     pG->vexnum = v;
  87.     pG->edgnum = e;
  88.     // 初始化"邻接表"的顶点
  89.     for(i=0; i<pG->vexnum; i++)
  90.     {
  91.         printf("vertex(%d): ", i);
  92.         pG->vexs[i].data = read_char();
  93.         pG->vexs[i].first_edge = NULL;
  94.     }

  95.     // 初始化"邻接表"的边
  96.     for(i=0; i<pG->edgnum; i++)
  97.     {
  98.         // 读取边的起始顶点和结束顶点
  99.         printf("edge(%d): ", i);
  100.         c1 = read_char();
  101.         c2 = read_char();

  102.         p1 = get_position(*pG, c1);
  103.         p2 = get_position(*pG, c2);
  104.         // 初始化node1
  105.         node1 = (ENode*)malloc(sizeof(ENode));
  106.         node1->ivex = p2;
  107.         node1->next_edge = NULL;
  108.         // 将node1链接到"p1所在链表的末尾"
  109.         if(pG->vexs[p1].first_edge == NULL)
  110.           pG->vexs[p1].first_edge = node1;
  111.         else
  112.             link_last(pG->vexs[p1].first_edge, node1);
  113.     }

  114.     return pG;
  115. }

  116. /*
  117. * 创建邻接表对应的图(用已提供的数据)
  118. */
  119. LGraph* create_example_lgraph()
  120. {
  121.     char c1, c2;
  122.     char vexs[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
  123.     char edges[][2] = {
  124.         {'A', 'B'},
  125.         {'B', 'C'},
  126.         {'B', 'E'},
  127.         {'B', 'F'},
  128.         {'C', 'E'},
  129.         {'D', 'C'},
  130.         {'E', 'B'},
  131.         {'E', 'D'},
  132.         {'F', 'G'}};
  133.     int vlen = LENGTH(vexs);
  134.     int elen = LENGTH(edges);
  135.     int i, p1, p2;
  136.     ENode *node1, *node2;
  137.     LGraph* pG;


  138.     if ((pG=(LGraph*)malloc(sizeof(LGraph))) == NULL )
  139.         return NULL;
  140.     memset(pG, 0, sizeof(LGraph));

  141.     // 初始化"顶点数"和"边数"
  142.     pG->vexnum = vlen;
  143.     pG->edgnum = elen;
  144.     // 初始化"邻接表"的顶点
  145.     for(i=0; i<pG->vexnum; i++)
  146.     {
  147.         pG->vexs[i].data = vexs[i];
  148.         pG->vexs[i].first_edge = NULL;
  149.     }

  150.     // 初始化"邻接表"的边
  151.     for(i=0; i<pG->edgnum; i++)
  152.     {
  153.         // 读取边的起始顶点和结束顶点
  154.         c1 = edges[i][0];
  155.         c2 = edges[i][1];

  156.         p1 = get_position(*pG, c1);
  157.         p2 = get_position(*pG, c2);
  158.         // 初始化node1
  159.         node1 = (ENode*)malloc(sizeof(ENode));
  160.         node1->ivex = p2;
  161.         node1->next_edge = NULL;
  162.         // 将node1链接到"p1所在链表的末尾"
  163.         if(pG->vexs[p1].first_edge == NULL)
  164.           pG->vexs[p1].first_edge = node1;
  165.         else
  166.             link_last(pG->vexs[p1].first_edge, node1);
  167.     }

  168.     return pG;
  169. }

  170. /*
  171. * 深度优先搜索遍历图的递归实现
  172. */
  173. static void DFS(LGraph G, int i, int *visited)
  174. {
  175.     int w;
  176.     ENode *node;

  177.     visited[i] = 1;
  178.     printf("%c ", G.vexs[i].data);
  179.     node = G.vexs[i].first_edge;
  180.     while (node != NULL)
  181.     {
  182.         if (!visited[node->ivex])
  183.             DFS(G, node->ivex, visited);
  184.         node = node->next_edge;
  185.     }
  186. }

  187. /*
  188. * 深度优先搜索遍历图
  189. */
  190. void DFSTraverse(LGraph G)
  191. {
  192.     int i;
  193.     int visited[MAX];       // 顶点访问标记

  194.     // 初始化所有顶点都没有被访问
  195.     for (i = 0; i < G.vexnum; i++)
  196.         visited[i] = 0;

  197.     printf("DFS: ");
  198.     for (i = 0; i < G.vexnum; i++)
  199.     {
  200.         if (!visited[i])
  201.             DFS(G, i, visited);
  202.     }
  203.     printf("\n");
  204. }

  205. /*
  206. * 广度优先搜索(类似于树的层次遍历)
  207. */
  208. void BFS(LGraph G)
  209. {
  210.     int head = 0;
  211.     int rear = 0;
  212.     int queue[MAX];     // 辅组队列
  213.     int visited[MAX];   // 顶点访问标记
  214.     int i, j, k;
  215.     ENode *node;

  216.     for (i = 0; i < G.vexnum; i++)
  217.         visited[i] = 0;

  218.     printf("BFS: ");
  219.     for (i = 0; i < G.vexnum; i++)
  220.     {
  221.         if (!visited[i])
  222.         {
  223.             visited[i] = 1;
  224.             printf("%c ", G.vexs[i].data);
  225.             queue[rear++] = i;  // 入队列
  226.         }
  227.         while (head != rear)
  228.         {
  229.             j = queue[head++];  // 出队列
  230.             node = G.vexs[j].first_edge;
  231.             while (node != NULL)
  232.             {
  233.                 k = node->ivex;
  234.                 if (!visited[k])
  235.                 {
  236.                     visited[k] = 1;
  237.                     printf("%c ", G.vexs[k].data);
  238.                     queue[rear++] = k;
  239.                 }
  240.                 node = node->next_edge;
  241.             }
  242.         }
  243.     }
  244.     printf("\n");
  245. }

  246. /*
  247. * 打印邻接表图
  248. */
  249. void print_lgraph(LGraph G)
  250. {
  251.     int i,j;
  252.     ENode *node;

  253.     printf("List Graph:\n");
  254.     for (i = 0; i < G.vexnum; i++)
  255.     {
  256.         printf("%d(%c): ", i, G.vexs[i].data);
  257.         node = G.vexs[i].first_edge;
  258.         while (node != NULL)
  259.         {
  260.             printf("%d(%c) ", node->ivex, G.vexs[node->ivex].data);
  261.             node = node->next_edge;
  262.         }
  263.         printf("\n");
  264.     }
  265. }

  266. void main()
  267. {
  268.     LGraph* pG;

  269.     // 自定义"图"(自己输入数据)
  270.     //pG = create_lgraph();
  271.     // 采用已有的"图"
  272.     pG = create_example_lgraph();

  273.     // 打印图
  274.     print_lgraph(*pG);
  275.     DFSTraverse(*pG);
  276.     BFS(*pG);
  277. }
复制代码


评分

参与人数 1荣誉 +5 鱼币 +5 贡献 +3 收起 理由
拈花小仙 + 5 + 5 + 3 感谢楼主无私奉献!

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2016-3-11 19:22:13 | 显示全部楼层
顶一个,现在也开始复习《数据结构与算法》了~
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-4-4 16:48:33 | 显示全部楼层
赞一个!
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-5-2 19:28:54 | 显示全部楼层
温馨提示,加入边的时候不一定非要插入到链表尾部,那样还会查找遍历整个链表,效率较低,可以直接插入到链表首部,写起来方便而且效率高^_^。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-5-26 20:16:52 | 显示全部楼层
队列用STL感觉好方便
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-12-24 18:20:55 From FishC Mobile | 显示全部楼层
给楼主点个赞~
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-9-7 15:19:08 | 显示全部楼层
感谢!
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2020-2-11 17:03:52 | 显示全部楼层
厉害
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2020-4-10 19:06:08 | 显示全部楼层
malloc后面如果不用memset可不可以
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-13 15:24

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表