|
|
发表于 2020-2-12 15:44:43
|
显示全部楼层
我还是忍不住又捡起了这个问题来研究,^_^
报错的原因我弄明白了
- graph = {'A': ['B', 'C',"F"],
- 'B': ['E'],
- 'C': ['E',"F"],
- 'D': ['E'],
- 'E': ['G'],
- 'F': ['H'],
- "G":["H"]}
- def find_shortest_path(graph, start, end, path=[]):
- path = path + [start]
- if start == end:
- return path
- shortest = None
- for node in graph[start]:
- if node not in path:
- newpath = find_shortest_path(graph, node, end, path)
- print(newpath)
- if newpath!=None:
- if not shortest or len(newpath) < len(shortest):
- shortest = newpath
- return shortest
-
- print(find_shortest_path(graph, 'A', 'H'))
复制代码
- ['A', 'B', 'E', 'G', 'H']
- ['A', 'B', 'E', 'G', 'H']
- ['A', 'B', 'E', 'G', 'H']
- ['A', 'B', 'E', 'G', 'H']
- ['A', 'C', 'E', 'G', 'H']
- ['A', 'C', 'E', 'G', 'H']
- ['A', 'C', 'E', 'G', 'H']
- ['A', 'C', 'F', 'H']
- ['A', 'C', 'F', 'H']
- ['A', 'C', 'F', 'H']
- ['A', 'F', 'H']
- ['A', 'F', 'H']
- ['A', 'F', 'H']
复制代码
这是这个算法对这个数据结构的所有搜索结果
可以看到,里面根本就没有 A - D 的路径
问题是 E 连着 D,但是graph这个数据结构中却没有说明
'E': ['G']
这个数据结构中只说明 E 连着 G,当然通过推导可以得到 E 连着 D,问题是这个算法中没有包含推导的代码
弄明白了问题所在,要得到解决方案也就简单了
只要把数据结构改成下面这样就可以了,把每一个顶点的对应关系都描述清楚就行了
- graph = {
- 'A': ['B', 'C', 'F'],
- 'B': ['A', 'E'],
- 'C': ['A', 'E', 'F'],
- 'D': ['E'],
- 'E': ['B', 'C', 'D', 'G'],
- 'F': ['A', 'C', 'H'],
- 'G': ['E', 'H'],
- 'H': ['F', 'G']
- }
- def find_shortest_path(graph, start, end, path=[]):
- path = path + [start]
- if start == end:
- return path
- shortest = None
- for node in graph[start]:
- if node not in path:
- newpath = find_shortest_path(graph, node, end, path)
- if newpath!=None:
- if not shortest or len(newpath) < len(shortest):
- shortest = newpath
- return shortest
-
- print(find_shortest_path(graph, 'A', 'D'))
复制代码
但是这样完整的说明对人类很不友好,这个问题也好解决
解决方案是
数据结构还是用简写,也就是下面这样
- graph = {'A': ['B', 'C',"F"],
- 'B': ['E'],
- 'C': ['E',"F"],
- 'D': ['E'],
- 'E': ['G'],
- 'F': ['H'],
- "G":["H"]}
复制代码
然后再写一个函数,用代码把这个简写的形式转换成完整的形式
我没有用python写转换函数,我还是在原来的C代码基础上写了转换函数,如果你愿意,你可以用python写一下转换函数,让我看看python中做这个转换有多么容易,^_^
这次修改了3个文件,main.c, graph.c, graph.h
list.c 和 list.h 没有改变,就不贴代码了
main.c
- #include "graph.h"
- int main(void)
- {
- graph_t graph = graph_init();
- graph_insert(graph, 'A', "BCF");
- graph_insert(graph, 'B', "E");
- graph_insert(graph, 'C', "EF");
- graph_insert(graph, 'D', "E");
- graph_insert(graph, 'E', "G");
- graph_insert(graph, 'F', "H");
- graph_insert(graph, 'G', "H");
- graph_format(graph);
-
- path_t path = graph_find_shortest_path(graph, 'A', 'D', NULL);
- graph_print_path(path);
- graph_free_path(path);
- graph_deinit(graph);
- return 0;
- }
复制代码
graph.h
- #ifndef _GRAPH_H_
- #define _GRAPH_H_
- #include "list.h"
- typedef char graph_elem_t;
- typedef struct
- {
- graph_elem_t v;
- list_t vs;
- } graph_node_t;
- typedef struct graph_tag
- {
- graph_node_t *node;
- size_t length;
- } *graph_t;
- graph_t graph_init(void);
- void graph_deinit(graph_t graph);
- void graph_insert(graph_t graph, graph_elem_t v, const char *vs);
- void graph_clear(graph_t graph);
- size_t graph_length(graph_t graph);
- bool graph_locate(graph_t graph, graph_elem_t v);
- typedef list_t path_t;
- typedef list_elem_t graph_vertex_t;
- void graph_format(graph_t graph);
- path_t graph_find_shortest_path(graph_t graph, graph_vertex_t start, graph_vertex_t end, path_t path);
- void graph_print_path(path_t path);
- void graph_free_path(path_t path);
- #endif
复制代码
graph.c
- #include "graph.h"
- #include <stdio.h>
- #include <stdlib.h>
- graph_t graph_init(void)
- {
- graph_t graph = malloc(sizeof(struct graph_tag));
- graph->length = 0;
- graph->node = NULL;
- return graph;
- }
- void graph_deinit(graph_t graph)
- {
- graph_clear(graph);
- free(graph);
- }
- void graph_insert(graph_t graph, graph_elem_t v, const char *vs)
- {
- ++graph->length;
- graph->node = realloc(graph->node, sizeof(graph_node_t) * graph->length);
- graph->node[graph->length - 1].v = v;
- graph->node[graph->length - 1].vs = list_init();
- for(size_t i = 0; vs[i]; ++i)
- list_append(graph->node[graph->length - 1].vs, vs[i]);
- }
- void graph_clear(graph_t graph)
- {
- for(size_t i = 0; i < graph_length(graph); ++i)
- list_deinit(graph->node[i].vs);
- free(graph->node);
- graph->node = NULL;
- graph->length = 0;
- }
- size_t graph_length(graph_t graph)
- {
- return graph->length;
- }
- bool graph_locate(graph_t graph, graph_elem_t v)
- {
- for(size_t i = 0; i < graph_length(graph); ++i)
- {
- if(graph->node[i].v == v)
- return true;
- }
- return false;
- }
- static list_t get_vs(graph_t graph, graph_vertex_t v)
- {
- for(size_t i = 0; i < graph_length(graph); ++i)
- {
- if(graph->node[i].v == v)
- return graph->node[i].vs;
- }
- return NULL;
- }
- void graph_format(graph_t graph)
- {
- for(size_t i = 0; i < graph_length(graph); ++i)
- {
- for(size_t j = 0; j < graph_length(graph); ++j)
- {
- if(i != j)
- {
- for(size_t k = 0; k < list_length(graph->node[j].vs); ++k)
- {
- list_elem_t e;
- list_get(graph->node[j].vs, k, &e);
- if(graph->node[i].v == e)
- {
- if(!list_locate(graph->node[i].vs, graph->node[j].v))
- list_append(graph->node[i].vs, graph->node[j].v);
- break;
- }
- if(!graph_locate(graph, e))
- graph_insert(graph, e, "");
- }
- }
- }
- }
- }
- path_t graph_find_shortest_path(graph_t graph, graph_vertex_t start, graph_vertex_t end, path_t path)
- {
- if(!path)
- path = list_init();
- list_append(path, start);
- if(start == end)
- return path;
- list_t shortest = NULL;
- list_t vs = get_vs(graph, start);
- for(size_t i = 0; i < list_length(vs); ++i)
- {
- graph_vertex_t node;
- list_get(vs, i, &node);
- if(!list_locate(path, node))
- {
- path_t newpath = graph_find_shortest_path(graph, node, end, list_clone(path));
- if(!list_empty(newpath))
- {
- if(!shortest || list_length(newpath) < list_length(shortest))
- {
- if(shortest)
- list_deinit(shortest);
- shortest = list_clone(newpath);
- }
- }
- list_deinit(newpath);
- }
- }
- list_deinit(path); // 这个path需要销毁
- if(!shortest)
- shortest = list_init();
- return shortest;
- }
- void graph_print_path(path_t path)
- {
- for(size_t i = 0; i < list_length(path); ++i)
- {
- list_elem_t e;
- list_get(path, i, &e);
- printf("%c ", e);
- }
- printf("\n");
- }
- void graph_free_path(path_t path)
- {
- list_deinit(path);
- }
复制代码 |
|