鱼C论坛

 找回密码
 立即注册
查看: 2484|回复: 19

[已解决]关于求最短路径法,哪位大侠能帮我翻转成C代码

[复制链接]
发表于 2020-2-11 17:04:53 | 显示全部楼层 |阅读模式

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

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

x
  1. graph = {'A': ['B', 'C',"F"],
  2.              'B': ['E'],
  3.              'C': ['E',"F"],
  4.              'D': ['E'],
  5.              'E': ['G'],
  6.              'F': ['H'],
  7.              "G":["H"]}

  8. def find_shortest_path(graph, start, end, path=[]):
  9.         path = path + [start]
  10.         if start == end:
  11.             return path
  12.         shortest = None
  13.         for node in graph[start]:
  14.             if node not in path:
  15.                 newpath = find_shortest_path(graph, node, end, path)
  16.                 if newpath!=None:
  17.                     if not shortest or len(newpath) < len(shortest):
  18.                         shortest = newpath
  19.         return shortest
  20.         
  21. print(find_shortest_path(graph, 'A', 'H'))     
复制代码
最佳答案
2020-2-12 02:28:21
6个小时可还行,^_^

下面简单说一下

1.
C语言中没有函数默认参数,所以这里只能加上NULL
  1. print(find_shortest_path(graph, 'A', 'H'))
复制代码

  1. path_t path = graph_find_shortest_path(graph, 'A', 'H', NULL);
复制代码


2.
C语言中没办法像这样静态初始化(编译时初始化),所以只能运行时初始化了
  1. graph = {'A': ['B', 'C',"F"],
  2.              'B': ['E'],
  3.              'C': ['E',"F"],
  4.              'D': ['E'],
  5.              'E': ['G'],
  6.              'F': ['H'],
  7.              "G":["H"]}
复制代码

  1.         graph_t graph = graph_init();
  2.         graph_insert(graph, 'A', "BCF");
  3.         graph_insert(graph, 'B', "E");
  4.         graph_insert(graph, 'C', "EF");
  5.         graph_insert(graph, 'D', "E");
  6.         graph_insert(graph, 'E', "G");
  7.         graph_insert(graph, 'F', "H");
  8.         graph_insert(graph, 'G', "H");
复制代码


还有,vs说我的代码有内存泄漏问题
我现在头有一点疼,^_^
明天再debug内存泄漏问题(明天指的是睡一觉起来)

下面贴代码
list.h
  1. #ifndef _LIST_H_
  2. #define _LIST_H_

  3. #include <stddef.h>
  4. #include <stdbool.h>

  5. typedef char list_elem_t;

  6. typedef struct list_node_tag
  7. {
  8.         list_elem_t e;
  9.         struct list_node_tag *next;
  10. } list_node_t;

  11. typedef struct list_tag
  12. {
  13.         list_node_t *data;
  14.         size_t length;
  15. } *list_t;

  16. list_t list_init(void);
  17. void list_deinit(list_t list);
  18. bool list_insert(list_t list, size_t index, list_elem_t e);
  19. bool list_delete(list_t list, size_t index);
  20. bool list_append(list_t list, list_elem_t e);
  21. bool list_get(list_t list, size_t index, list_elem_t *e);
  22. void list_clear(list_t list);
  23. bool list_empty(list_t list);
  24. size_t list_length(list_t list);
  25. bool list_locate(list_t list, list_elem_t e);
  26. list_t list_clone(list_t list);

  27. #endif
复制代码


list.c
  1. #include "list.h"
  2. #include <stdlib.h>

  3. list_t list_init(void)
  4. {
  5.         list_t list = malloc(sizeof(struct list_tag));
  6.         list->length = 0;
  7.         list->data = malloc(sizeof(list_node_t));
  8.         list->data->e = 0;
  9.         list->data->next = NULL;
  10.         return list;
  11. }

  12. void list_deinit(list_t list)
  13. {
  14.         list_clear(list);
  15.         free(list->data);
  16.         free(list);
  17. }

  18. bool list_insert(list_t list, size_t index, list_elem_t e)
  19. {
  20.         if(list_length(list) < index)
  21.                 return false;

  22.         list_node_t *p = list->data;
  23.         while(index--)
  24.                 p = p->next;

  25.         list_node_t *node = malloc(sizeof(list_node_t));
  26.         node->e = e;
  27.         node->next = p->next;
  28.         p->next = node;
  29.         ++list->length;
  30.         return true;
  31. }

  32. bool list_delete(list_t list, size_t index)
  33. {
  34.         if(list_empty(list))
  35.                 return false;
  36.         if(list_length(list) <= index)
  37.                 return false;

  38.         list_node_t *p = list->data;
  39.         while(index--)
  40.                 p = p->next;

  41.         list_node_t *temp = p->next;
  42.         p->next = p->next->next;
  43.         free(temp);
  44.         --list->length;
  45.         return true;
  46. }

  47. bool list_append(list_t list, list_elem_t e)
  48. {
  49.         return list_insert(list, list_length(list), e);
  50. }

  51. bool list_get(list_t list, size_t index, list_elem_t *e)
  52. {
  53.         if(list_empty(list))
  54.                 return false;
  55.         if(list_length(list) <= index)
  56.                 return false;

  57.         list_node_t *p = list->data->next;
  58.         while(index--)
  59.                 p = p->next;
  60.         *e = p->e;
  61.         return true;
  62. }

  63. void list_clear(list_t list)
  64. {
  65.         while(!list_empty(list))
  66.                 list_delete(list, 0);
  67. }

  68. bool list_empty(list_t list)
  69. {
  70.         return !list_length(list);
  71. }

  72. size_t list_length(list_t list)
  73. {
  74.         return list->length;
  75. }

  76. bool list_locate(list_t list, list_elem_t e)
  77. {
  78.         for(size_t i = 0; i < list_length(list); ++i)
  79.         {
  80.                 list_elem_t elem;
  81.                 list_get(list, i, &elem);
  82.                 if(elem == e)
  83.                         return true;
  84.         }
  85.         return false;
  86. }

  87. list_t list_clone(list_t list)
  88. {
  89.         list_t clone = list_init();
  90.         for(size_t i = 0; i < list_length(list); ++i)
  91.         {
  92.                 list_elem_t e;
  93.                 list_get(list, i, &e);
  94.                 list_append(clone, e);
  95.         }
  96.         return clone;
  97. }
复制代码


graph.h
  1. #ifndef _GRAPH_H_
  2. #define _GRAPH_H_

  3. #include "list.h"

  4. typedef char graph_elem_t;

  5. typedef struct
  6. {
  7.         graph_elem_t v;
  8.         list_t vs;
  9. } graph_node_t;

  10. typedef struct graph_tag
  11. {
  12.         graph_node_t *node;
  13.         size_t length;
  14. } *graph_t;

  15. graph_t graph_init(void);
  16. void graph_deinit(graph_t graph);
  17. void graph_insert(graph_t graph, graph_elem_t v, const char *vs);
  18. void graph_clear(graph_t graph);

  19. typedef list_t path_t;
  20. typedef list_elem_t graph_vertex_t;
  21. path_t graph_find_shortest_path(graph_t graph, graph_vertex_t start, graph_vertex_t end, path_t path);
  22. void graph_print_path(path_t path);
  23. void graph_free_path(path_t path);

  24. #endif
复制代码


graph.c
  1. #include "graph.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>

  4. graph_t graph_init(void)
  5. {
  6.         graph_t graph = malloc(sizeof(struct graph_tag));
  7.         graph->length = 0;
  8.         graph->node = NULL;
  9.         return graph;
  10. }

  11. void graph_deinit(graph_t graph)
  12. {
  13.         graph_clear(graph);
  14.         free(graph);
  15. }

  16. void graph_insert(graph_t graph, graph_elem_t v, const char *vs)
  17. {
  18.         ++graph->length;
  19.         graph->node = realloc(graph->node, sizeof(graph_node_t) * graph->length);
  20.         graph->node[graph->length - 1].v = v;
  21.         graph->node[graph->length - 1].vs = list_init();
  22.         for(size_t i = 0; vs[i]; ++i)
  23.                 list_append(graph->node[graph->length - 1].vs, vs[i]);
  24. }

  25. void graph_clear(graph_t graph)
  26. {
  27.         for(size_t i = 0; i < graph->length; ++i)
  28.                 list_deinit(graph->node[i].vs);
  29.         free(graph->node);
  30.         graph->node = NULL;
  31.         graph->length = 0;
  32. }

  33. static list_t get_vs(graph_t graph, graph_vertex_t v)
  34. {
  35.         for(size_t i = 0; i < graph->length; ++i)
  36.         {
  37.                 if(graph->node[i].v == v)
  38.                         return graph->node[i].vs;
  39.         }
  40.         return NULL;
  41. }

  42. path_t graph_find_shortest_path(graph_t graph, graph_vertex_t start, graph_vertex_t end, path_t path)
  43. {
  44.         if(!path)
  45.                 path = list_init();

  46.         list_append(path, start);
  47.         if(start == end)
  48.                 return path;

  49.         list_t shortest = NULL;

  50.         list_t vs = get_vs(graph, start);
  51.         for(size_t i = 0; i < list_length(vs); ++i)
  52.         {
  53.                 graph_vertex_t node;
  54.                 list_get(vs, i, &node);
  55.                 if(!list_locate(path, node))
  56.                 {
  57.                         path_t newpath = graph_find_shortest_path(graph, node, end, list_clone(path));
  58.                         if(!list_empty(newpath))
  59.                         {
  60.                                 if(!shortest || list_length(newpath) < list_length(shortest))
  61.                                 {
  62.                                         if(shortest)
  63.                                                 list_deinit(shortest);
  64.                                         shortest = list_clone(newpath);
  65.                                 }
  66.                                 list_deinit(newpath);
  67.                         }
  68.                 }
  69.         }
  70.         return shortest;
  71. }

  72. void graph_print_path(path_t path)
  73. {
  74.         for(size_t i = 0; i < path->length; ++i)
  75.         {
  76.                 list_elem_t e;
  77.                 list_get(path, i, &e);
  78.                 printf("%c ", e);
  79.         }
  80.         printf("\n");
  81. }

  82. void graph_free_path(path_t path)
  83. {
  84.         list_deinit(path);
  85. }
复制代码


main.c
  1. #include "graph.h"

  2. int main(void)
  3. {
  4.         graph_t graph = graph_init();
  5.         graph_insert(graph, 'A', "BCF");
  6.         graph_insert(graph, 'B', "E");
  7.         graph_insert(graph, 'C', "EF");
  8.         graph_insert(graph, 'D', "E");
  9.         graph_insert(graph, 'E', "G");
  10.         graph_insert(graph, 'F', "H");
  11.         graph_insert(graph, 'G', "H");
  12.        
  13.         path_t path = graph_find_shortest_path(graph, 'A', 'H', NULL);
  14.         graph_print_path(path);
  15.         graph_free_path(path);

  16.         graph_deinit(graph);
  17.         return 0;
  18. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2020-2-11 17:13:50 | 显示全部楼层
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-11 17:16:15 | 显示全部楼层

有点难不太会
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-2-11 19:05:43 From FishC Mobile | 显示全部楼层
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-11 19:08:46 | 显示全部楼层

我研究研究
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-11 19:47:51 | 显示全部楼层
  1. graph = {'A': ['B', 'C',"F"],
  2.              'B': ['E'],
  3.              'C': ['E',"F"],
  4.              'D': ['E'],
  5.              'E': ['G'],
  6.              'F': ['H'],
  7.              "G":["H"]}
复制代码


graph这个变量表示的图是这个样子吗?

1.png
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-2-11 19:58:56 | 显示全部楼层
人造人 发表于 2020-2-11 19:47
graph这个变量表示的图是这个样子吗?

一点不差  
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-11 20:08:06 | 显示全部楼层
必须是 C 吗?不能用 C++ ?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-2-11 20:09:23 | 显示全部楼层
人造人 发表于 2020-2-11 20:08
必须是 C 吗?不能用 C++ ?

嗯,最好不用加加  因为加加有些特有的库   而c 都是原生态的
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-11 20:11:31 | 显示全部楼层
wp231957 发表于 2020-2-11 20:09
嗯,最好不用加加  因为加加有些特有的库   而c 都是原生态的

我试试吧
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-2-11 20:40:06 From FishC Mobile | 显示全部楼层
人造人 发表于 2020-2-11 20:11
我试试吧

辛苦了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-12 02:28:21 | 显示全部楼层    本楼为最佳答案   
6个小时可还行,^_^

下面简单说一下

1.
C语言中没有函数默认参数,所以这里只能加上NULL
  1. print(find_shortest_path(graph, 'A', 'H'))
复制代码

  1. path_t path = graph_find_shortest_path(graph, 'A', 'H', NULL);
复制代码


2.
C语言中没办法像这样静态初始化(编译时初始化),所以只能运行时初始化了
  1. graph = {'A': ['B', 'C',"F"],
  2.              'B': ['E'],
  3.              'C': ['E',"F"],
  4.              'D': ['E'],
  5.              'E': ['G'],
  6.              'F': ['H'],
  7.              "G":["H"]}
复制代码

  1.         graph_t graph = graph_init();
  2.         graph_insert(graph, 'A', "BCF");
  3.         graph_insert(graph, 'B', "E");
  4.         graph_insert(graph, 'C', "EF");
  5.         graph_insert(graph, 'D', "E");
  6.         graph_insert(graph, 'E', "G");
  7.         graph_insert(graph, 'F', "H");
  8.         graph_insert(graph, 'G', "H");
复制代码


还有,vs说我的代码有内存泄漏问题
我现在头有一点疼,^_^
明天再debug内存泄漏问题(明天指的是睡一觉起来)

下面贴代码
list.h
  1. #ifndef _LIST_H_
  2. #define _LIST_H_

  3. #include <stddef.h>
  4. #include <stdbool.h>

  5. typedef char list_elem_t;

  6. typedef struct list_node_tag
  7. {
  8.         list_elem_t e;
  9.         struct list_node_tag *next;
  10. } list_node_t;

  11. typedef struct list_tag
  12. {
  13.         list_node_t *data;
  14.         size_t length;
  15. } *list_t;

  16. list_t list_init(void);
  17. void list_deinit(list_t list);
  18. bool list_insert(list_t list, size_t index, list_elem_t e);
  19. bool list_delete(list_t list, size_t index);
  20. bool list_append(list_t list, list_elem_t e);
  21. bool list_get(list_t list, size_t index, list_elem_t *e);
  22. void list_clear(list_t list);
  23. bool list_empty(list_t list);
  24. size_t list_length(list_t list);
  25. bool list_locate(list_t list, list_elem_t e);
  26. list_t list_clone(list_t list);

  27. #endif
复制代码


list.c
  1. #include "list.h"
  2. #include <stdlib.h>

  3. list_t list_init(void)
  4. {
  5.         list_t list = malloc(sizeof(struct list_tag));
  6.         list->length = 0;
  7.         list->data = malloc(sizeof(list_node_t));
  8.         list->data->e = 0;
  9.         list->data->next = NULL;
  10.         return list;
  11. }

  12. void list_deinit(list_t list)
  13. {
  14.         list_clear(list);
  15.         free(list->data);
  16.         free(list);
  17. }

  18. bool list_insert(list_t list, size_t index, list_elem_t e)
  19. {
  20.         if(list_length(list) < index)
  21.                 return false;

  22.         list_node_t *p = list->data;
  23.         while(index--)
  24.                 p = p->next;

  25.         list_node_t *node = malloc(sizeof(list_node_t));
  26.         node->e = e;
  27.         node->next = p->next;
  28.         p->next = node;
  29.         ++list->length;
  30.         return true;
  31. }

  32. bool list_delete(list_t list, size_t index)
  33. {
  34.         if(list_empty(list))
  35.                 return false;
  36.         if(list_length(list) <= index)
  37.                 return false;

  38.         list_node_t *p = list->data;
  39.         while(index--)
  40.                 p = p->next;

  41.         list_node_t *temp = p->next;
  42.         p->next = p->next->next;
  43.         free(temp);
  44.         --list->length;
  45.         return true;
  46. }

  47. bool list_append(list_t list, list_elem_t e)
  48. {
  49.         return list_insert(list, list_length(list), e);
  50. }

  51. bool list_get(list_t list, size_t index, list_elem_t *e)
  52. {
  53.         if(list_empty(list))
  54.                 return false;
  55.         if(list_length(list) <= index)
  56.                 return false;

  57.         list_node_t *p = list->data->next;
  58.         while(index--)
  59.                 p = p->next;
  60.         *e = p->e;
  61.         return true;
  62. }

  63. void list_clear(list_t list)
  64. {
  65.         while(!list_empty(list))
  66.                 list_delete(list, 0);
  67. }

  68. bool list_empty(list_t list)
  69. {
  70.         return !list_length(list);
  71. }

  72. size_t list_length(list_t list)
  73. {
  74.         return list->length;
  75. }

  76. bool list_locate(list_t list, list_elem_t e)
  77. {
  78.         for(size_t i = 0; i < list_length(list); ++i)
  79.         {
  80.                 list_elem_t elem;
  81.                 list_get(list, i, &elem);
  82.                 if(elem == e)
  83.                         return true;
  84.         }
  85.         return false;
  86. }

  87. list_t list_clone(list_t list)
  88. {
  89.         list_t clone = list_init();
  90.         for(size_t i = 0; i < list_length(list); ++i)
  91.         {
  92.                 list_elem_t e;
  93.                 list_get(list, i, &e);
  94.                 list_append(clone, e);
  95.         }
  96.         return clone;
  97. }
复制代码


graph.h
  1. #ifndef _GRAPH_H_
  2. #define _GRAPH_H_

  3. #include "list.h"

  4. typedef char graph_elem_t;

  5. typedef struct
  6. {
  7.         graph_elem_t v;
  8.         list_t vs;
  9. } graph_node_t;

  10. typedef struct graph_tag
  11. {
  12.         graph_node_t *node;
  13.         size_t length;
  14. } *graph_t;

  15. graph_t graph_init(void);
  16. void graph_deinit(graph_t graph);
  17. void graph_insert(graph_t graph, graph_elem_t v, const char *vs);
  18. void graph_clear(graph_t graph);

  19. typedef list_t path_t;
  20. typedef list_elem_t graph_vertex_t;
  21. path_t graph_find_shortest_path(graph_t graph, graph_vertex_t start, graph_vertex_t end, path_t path);
  22. void graph_print_path(path_t path);
  23. void graph_free_path(path_t path);

  24. #endif
复制代码


graph.c
  1. #include "graph.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>

  4. graph_t graph_init(void)
  5. {
  6.         graph_t graph = malloc(sizeof(struct graph_tag));
  7.         graph->length = 0;
  8.         graph->node = NULL;
  9.         return graph;
  10. }

  11. void graph_deinit(graph_t graph)
  12. {
  13.         graph_clear(graph);
  14.         free(graph);
  15. }

  16. void graph_insert(graph_t graph, graph_elem_t v, const char *vs)
  17. {
  18.         ++graph->length;
  19.         graph->node = realloc(graph->node, sizeof(graph_node_t) * graph->length);
  20.         graph->node[graph->length - 1].v = v;
  21.         graph->node[graph->length - 1].vs = list_init();
  22.         for(size_t i = 0; vs[i]; ++i)
  23.                 list_append(graph->node[graph->length - 1].vs, vs[i]);
  24. }

  25. void graph_clear(graph_t graph)
  26. {
  27.         for(size_t i = 0; i < graph->length; ++i)
  28.                 list_deinit(graph->node[i].vs);
  29.         free(graph->node);
  30.         graph->node = NULL;
  31.         graph->length = 0;
  32. }

  33. static list_t get_vs(graph_t graph, graph_vertex_t v)
  34. {
  35.         for(size_t i = 0; i < graph->length; ++i)
  36.         {
  37.                 if(graph->node[i].v == v)
  38.                         return graph->node[i].vs;
  39.         }
  40.         return NULL;
  41. }

  42. path_t graph_find_shortest_path(graph_t graph, graph_vertex_t start, graph_vertex_t end, path_t path)
  43. {
  44.         if(!path)
  45.                 path = list_init();

  46.         list_append(path, start);
  47.         if(start == end)
  48.                 return path;

  49.         list_t shortest = NULL;

  50.         list_t vs = get_vs(graph, start);
  51.         for(size_t i = 0; i < list_length(vs); ++i)
  52.         {
  53.                 graph_vertex_t node;
  54.                 list_get(vs, i, &node);
  55.                 if(!list_locate(path, node))
  56.                 {
  57.                         path_t newpath = graph_find_shortest_path(graph, node, end, list_clone(path));
  58.                         if(!list_empty(newpath))
  59.                         {
  60.                                 if(!shortest || list_length(newpath) < list_length(shortest))
  61.                                 {
  62.                                         if(shortest)
  63.                                                 list_deinit(shortest);
  64.                                         shortest = list_clone(newpath);
  65.                                 }
  66.                                 list_deinit(newpath);
  67.                         }
  68.                 }
  69.         }
  70.         return shortest;
  71. }

  72. void graph_print_path(path_t path)
  73. {
  74.         for(size_t i = 0; i < path->length; ++i)
  75.         {
  76.                 list_elem_t e;
  77.                 list_get(path, i, &e);
  78.                 printf("%c ", e);
  79.         }
  80.         printf("\n");
  81. }

  82. void graph_free_path(path_t path)
  83. {
  84.         list_deinit(path);
  85. }
复制代码


main.c
  1. #include "graph.h"

  2. int main(void)
  3. {
  4.         graph_t graph = graph_init();
  5.         graph_insert(graph, 'A', "BCF");
  6.         graph_insert(graph, 'B', "E");
  7.         graph_insert(graph, 'C', "EF");
  8.         graph_insert(graph, 'D', "E");
  9.         graph_insert(graph, 'E', "G");
  10.         graph_insert(graph, 'F', "H");
  11.         graph_insert(graph, 'G', "H");
  12.        
  13.         path_t path = graph_find_shortest_path(graph, 'A', 'H', NULL);
  14.         graph_print_path(path);
  15.         graph_free_path(path);

  16.         graph_deinit(graph);
  17.         return 0;
  18. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-12 02:43:31 | 显示全部楼层
本帖最后由 人造人 于 2020-2-12 02:45 编辑

“2.
C语言中没办法像这样静态初始化(编译时初始化),所以只能运行时初始化了”

我后来想了想,用字符串的话也许可以做到静态初始化,但是在这之前我想了好久也想不到如何静态初始化(当然那时还没有引入字符串)
不管怎么说,反正代码已经写完了,就不改了
bug当然还要修复
^_^
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-2-12 06:33:01 From FishC Mobile | 显示全部楼层
人造人 发表于 2020-2-12 02:43
“2.
C语言中没办法像这样静态初始化(编译时初始化),所以只能运行时初始化了”


十分感谢
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-12 12:43:05 | 显示全部楼层
只添加了一条语句

  1. path_t graph_find_shortest_path(graph_t graph, graph_vertex_t start, graph_vertex_t end, path_t path)
  2. {
  3.         if(!path)
  4.                 path = list_init();

  5.         list_append(path, start);
  6.         if(start == end)
  7.                 return path;

  8.         list_t shortest = NULL;

  9.         list_t vs = get_vs(graph, start);
  10.         for(size_t i = 0; i < list_length(vs); ++i)
  11.         {
  12.                 graph_vertex_t node;
  13.                 list_get(vs, i, &node);
  14.                 if(!list_locate(path, node))
  15.                 {
  16.                         path_t newpath = graph_find_shortest_path(graph, node, end, list_clone(path));
  17.                         if(!list_empty(newpath))
  18.                         {
  19.                                 if(!shortest || list_length(newpath) < list_length(shortest))
  20.                                 {
  21.                                         if(shortest)
  22.                                                 list_deinit(shortest);
  23.                                         shortest = list_clone(newpath);
  24.                                 }
  25.                                 list_deinit(newpath);
  26.                         }
  27.                 }
  28.         }
  29.         list_deinit(path);                // 这个path需要销毁
  30.         return shortest;
  31. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-12 12:51:53 | 显示全部楼层
还有,你这个代码不能搜索 A 到 D  ?
我解决了我的代码的内存泄漏问题后,我就是好奇我的代码能不能搜索其他路径,然后发现报错,试了几个都报错,我又试了你的代码,也报错

1.png
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-2-12 12:58:13 | 显示全部楼层
人造人 发表于 2020-2-12 12:51
还有,你这个代码不能搜索 A 到 D  ?
我解决了我的代码的内存泄漏问题后,我就是好奇我的代码能不能搜索其 ...

一样的,我不太懂  图这个数据结构  代码都是网上copy的

不知道这种情况下  这个d  属于什么状态   因为他和别人是不闭合的   所以 涉及到d的路径  都是报错的

如果d是可以走的   那么1楼代码就是问题代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-12 13:04:01 | 显示全部楼层
wp231957 发表于 2020-2-12 12:58
一样的,我不太懂  图这个数据结构  代码都是网上copy的

不知道这种情况下  这个d  属于什么状态    ...

嗯,一样的,图我学的也不好,这个问题就这样了
^_^
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-12 15:44:43 | 显示全部楼层
我还是忍不住又捡起了这个问题来研究,^_^

报错的原因我弄明白了


  1. graph = {'A': ['B', 'C',"F"],
  2.              'B': ['E'],
  3.              'C': ['E',"F"],
  4.              'D': ['E'],
  5.              'E': ['G'],
  6.              'F': ['H'],
  7.              "G":["H"]}

  8. def find_shortest_path(graph, start, end, path=[]):
  9.         path = path + [start]
  10.         if start == end:
  11.             return path
  12.         shortest = None
  13.         for node in graph[start]:
  14.             if node not in path:
  15.                 newpath = find_shortest_path(graph, node, end, path)
  16.                 print(newpath)
  17.                 if newpath!=None:
  18.                     if not shortest or len(newpath) < len(shortest):
  19.                         shortest = newpath
  20.         return shortest
  21.         
  22. print(find_shortest_path(graph, 'A', 'H'))
复制代码


  1. ['A', 'B', 'E', 'G', 'H']
  2. ['A', 'B', 'E', 'G', 'H']
  3. ['A', 'B', 'E', 'G', 'H']
  4. ['A', 'B', 'E', 'G', 'H']
  5. ['A', 'C', 'E', 'G', 'H']
  6. ['A', 'C', 'E', 'G', 'H']
  7. ['A', 'C', 'E', 'G', 'H']
  8. ['A', 'C', 'F', 'H']
  9. ['A', 'C', 'F', 'H']
  10. ['A', 'C', 'F', 'H']
  11. ['A', 'F', 'H']
  12. ['A', 'F', 'H']
  13. ['A', 'F', 'H']
复制代码


这是这个算法对这个数据结构的所有搜索结果
可以看到,里面根本就没有 A - D 的路径

问题是 E 连着 D,但是graph这个数据结构中却没有说明
'E': ['G']
这个数据结构中只说明 E 连着 G,当然通过推导可以得到 E 连着 D,问题是这个算法中没有包含推导的代码


弄明白了问题所在,要得到解决方案也就简单了
只要把数据结构改成下面这样就可以了,把每一个顶点的对应关系都描述清楚就行了

  1. graph = {
  2.         'A': ['B', 'C', 'F'],
  3.         'B': ['A', 'E'],
  4.         'C': ['A', 'E', 'F'],
  5.         'D': ['E'],
  6.         'E': ['B', 'C', 'D', 'G'],
  7.         'F': ['A', 'C', 'H'],
  8.         'G': ['E', 'H'],
  9.         'H': ['F', 'G']
  10. }


  11. def find_shortest_path(graph, start, end, path=[]):
  12.         path = path + [start]
  13.         if start == end:
  14.             return path
  15.         shortest = None
  16.         for node in graph[start]:
  17.             if node not in path:
  18.                 newpath = find_shortest_path(graph, node, end, path)
  19.                 if newpath!=None:
  20.                     if not shortest or len(newpath) < len(shortest):
  21.                         shortest = newpath
  22.         return shortest
  23.         
  24. print(find_shortest_path(graph, 'A', 'D'))
复制代码

  1. ['A', 'B', 'E', 'D']
复制代码


但是这样完整的说明对人类很不友好,这个问题也好解决
解决方案是
数据结构还是用简写,也就是下面这样
  1. graph = {'A': ['B', 'C',"F"],
  2.              'B': ['E'],
  3.              'C': ['E',"F"],
  4.              'D': ['E'],
  5.              'E': ['G'],
  6.              'F': ['H'],
  7.              "G":["H"]}
复制代码


然后再写一个函数,用代码把这个简写的形式转换成完整的形式

我没有用python写转换函数,我还是在原来的C代码基础上写了转换函数,如果你愿意,你可以用python写一下转换函数,让我看看python中做这个转换有多么容易,^_^

这次修改了3个文件,main.c, graph.c, graph.h
list.c 和 list.h 没有改变,就不贴代码了

main.c
  1. #include "graph.h"

  2. int main(void)
  3. {
  4.         graph_t graph = graph_init();
  5.         graph_insert(graph, 'A', "BCF");
  6.         graph_insert(graph, 'B', "E");
  7.         graph_insert(graph, 'C', "EF");
  8.         graph_insert(graph, 'D', "E");
  9.         graph_insert(graph, 'E', "G");
  10.         graph_insert(graph, 'F', "H");
  11.         graph_insert(graph, 'G', "H");
  12.         graph_format(graph);
  13.        
  14.         path_t path = graph_find_shortest_path(graph, 'A', 'D', NULL);
  15.         graph_print_path(path);
  16.         graph_free_path(path);

  17.         graph_deinit(graph);
  18.         return 0;
  19. }
复制代码


graph.h
  1. #ifndef _GRAPH_H_
  2. #define _GRAPH_H_

  3. #include "list.h"

  4. typedef char graph_elem_t;

  5. typedef struct
  6. {
  7.         graph_elem_t v;
  8.         list_t vs;
  9. } graph_node_t;

  10. typedef struct graph_tag
  11. {
  12.         graph_node_t *node;
  13.         size_t length;
  14. } *graph_t;

  15. graph_t graph_init(void);
  16. void graph_deinit(graph_t graph);
  17. void graph_insert(graph_t graph, graph_elem_t v, const char *vs);
  18. void graph_clear(graph_t graph);
  19. size_t graph_length(graph_t graph);
  20. bool graph_locate(graph_t graph, graph_elem_t v);

  21. typedef list_t path_t;
  22. typedef list_elem_t graph_vertex_t;
  23. void graph_format(graph_t graph);
  24. path_t graph_find_shortest_path(graph_t graph, graph_vertex_t start, graph_vertex_t end, path_t path);
  25. void graph_print_path(path_t path);
  26. void graph_free_path(path_t path);

  27. #endif
复制代码


graph.c
  1. #include "graph.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>

  4. graph_t graph_init(void)
  5. {
  6.         graph_t graph = malloc(sizeof(struct graph_tag));
  7.         graph->length = 0;
  8.         graph->node = NULL;
  9.         return graph;
  10. }

  11. void graph_deinit(graph_t graph)
  12. {
  13.         graph_clear(graph);
  14.         free(graph);
  15. }

  16. void graph_insert(graph_t graph, graph_elem_t v, const char *vs)
  17. {
  18.         ++graph->length;
  19.         graph->node = realloc(graph->node, sizeof(graph_node_t) * graph->length);
  20.         graph->node[graph->length - 1].v = v;
  21.         graph->node[graph->length - 1].vs = list_init();
  22.         for(size_t i = 0; vs[i]; ++i)
  23.                 list_append(graph->node[graph->length - 1].vs, vs[i]);
  24. }

  25. void graph_clear(graph_t graph)
  26. {
  27.         for(size_t i = 0; i < graph_length(graph); ++i)
  28.                 list_deinit(graph->node[i].vs);
  29.         free(graph->node);
  30.         graph->node = NULL;
  31.         graph->length = 0;
  32. }

  33. size_t graph_length(graph_t graph)
  34. {
  35.         return graph->length;
  36. }

  37. bool graph_locate(graph_t graph, graph_elem_t v)
  38. {
  39.         for(size_t i = 0; i < graph_length(graph); ++i)
  40.         {
  41.                 if(graph->node[i].v == v)
  42.                         return true;
  43.         }
  44.         return false;
  45. }

  46. static list_t get_vs(graph_t graph, graph_vertex_t v)
  47. {
  48.         for(size_t i = 0; i < graph_length(graph); ++i)
  49.         {
  50.                 if(graph->node[i].v == v)
  51.                         return graph->node[i].vs;
  52.         }
  53.         return NULL;
  54. }

  55. void graph_format(graph_t graph)
  56. {
  57.         for(size_t i = 0; i < graph_length(graph); ++i)
  58.         {
  59.                 for(size_t j = 0; j < graph_length(graph); ++j)
  60.                 {
  61.                         if(i != j)
  62.                         {
  63.                                 for(size_t k = 0; k < list_length(graph->node[j].vs); ++k)
  64.                                 {
  65.                                         list_elem_t e;
  66.                                         list_get(graph->node[j].vs, k, &e);
  67.                                         if(graph->node[i].v == e)
  68.                                         {
  69.                                                 if(!list_locate(graph->node[i].vs, graph->node[j].v))
  70.                                                         list_append(graph->node[i].vs, graph->node[j].v);
  71.                                                 break;
  72.                                         }
  73.                                         if(!graph_locate(graph, e))
  74.                                                 graph_insert(graph, e, "");
  75.                                 }
  76.                         }
  77.                 }
  78.         }
  79. }

  80. path_t graph_find_shortest_path(graph_t graph, graph_vertex_t start, graph_vertex_t end, path_t path)
  81. {
  82.         if(!path)
  83.                 path = list_init();

  84.         list_append(path, start);
  85.         if(start == end)
  86.                 return path;

  87.         list_t shortest = NULL;

  88.         list_t vs = get_vs(graph, start);
  89.         for(size_t i = 0; i < list_length(vs); ++i)
  90.         {
  91.                 graph_vertex_t node;
  92.                 list_get(vs, i, &node);
  93.                 if(!list_locate(path, node))
  94.                 {
  95.                         path_t newpath = graph_find_shortest_path(graph, node, end, list_clone(path));
  96.                         if(!list_empty(newpath))
  97.                         {
  98.                                 if(!shortest || list_length(newpath) < list_length(shortest))
  99.                                 {
  100.                                         if(shortest)
  101.                                                 list_deinit(shortest);
  102.                                         shortest = list_clone(newpath);
  103.                                 }
  104.                         }
  105.                         list_deinit(newpath);
  106.                 }
  107.         }
  108.         list_deinit(path);                // 这个path需要销毁
  109.         if(!shortest)
  110.                 shortest = list_init();
  111.         return shortest;
  112. }

  113. void graph_print_path(path_t path)
  114. {
  115.         for(size_t i = 0; i < list_length(path); ++i)
  116.         {
  117.                 list_elem_t e;
  118.                 list_get(path, i, &e);
  119.                 printf("%c ", e);
  120.         }
  121.         printf("\n");
  122. }

  123. void graph_free_path(path_t path)
  124. {
  125.         list_deinit(path);
  126. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-2-12 15:46:40 From FishC Mobile | 显示全部楼层
人造人 发表于 2020-2-12 15:44
我还是忍不住又捡起了这个问题来研究,^_^

报错的原因我弄明白了

谢谢我会一一测试的
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-3-3 14:13

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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