/// <summary> /// /// </summary> /// <param name="id">ID ребра</param> /// <param name="node_out">Ссылка на старт</param> /// <param name="node_in">Ссылка на конец</param> /// <param name="weight">Вес ребра</param> public EdgeInWork(int id, NodeInWork node_out, NodeInWork node_in, double weight) { this.id = id; this.node_out = node_out; this.node_in = node_in; this.weight = weight; }
public bool TryGetValue(int id, out NodeInWork value) { return(nodes.TryGetValue(id, out value)); }
public OpenListValue(NodeInWork Node) { RealWeight = new double(); HeuristicWeight = new double(); this.Node = Node; }
public OpenListValue(NodeInWork Node, double RealWeight, double HeuristicWeight) { this.RealWeight = RealWeight; this.HeuristicWeight = HeuristicWeight; this.Node = Node; }
/// <summary> /// Нахождение кратчайшего пути между двумя вершинами в графе по ССЫЛКАМ на вершины /// </summary> /// <param name="node_start">Ссылка на стартовую вершину</param> /// <param name="node_finish">Ссылка на конечную вершину</param> /// <returns>Возвращает список ребер из которых строится маршут из node_start к node_finish, при невозможности его построения - Null</returns> public Path MakePath(NodeInWork node_strart_link, NodeInWork node_finish_link) { if (node_strart_link == node_finish_link || node_strart_link == null || node_finish_link == null) { return(null); } //Инициализация коллекций для алгоритма А* //Открытый список Dictionary <NodeInWork, OpenListValue> open = new Dictionary <NodeInWork, OpenListValue>(); //Сортированный список эвритических фукнций открытого списка List <OpenListValue> open_sorted = new List <OpenListValue>(); //Маршрутный список Dictionary <NodeInWork, RoadInfo> road_map = new Dictionary <NodeInWork, RoadInfo>(); //Стартовая инициализация алгоритма //Сохранения ключевых ссылок графа var opn_start = new OpenListValue(node_strart_link, 0, 0); open.Add(node_strart_link, opn_start); open_sorted.Add(opn_start); road_map.Add(node_strart_link, new RoadInfo(null, null)); NodeInWork curr = null; //Проход алгоритма А* do { var opn_curr_weight = open_sorted[open_sorted.Count - 1]; curr = opn_curr_weight.Node; //Если финальная нода была признана самой "легкой", то лучше маршрута уже не будет. Конец алгоритма. if (curr == node_finish_link) { break; } open.Remove(curr); road_map[curr].close = true; open_sorted.RemoveAt(open_sorted.Count - 1); //Проверка всех соседей пограничной вершины на предмет веса их маршрута + эвристики foreach (EdgeInWork edge in curr.edge) { RoadInfo rdm; road_map.TryGetValue(edge.Node_in, out rdm); if (rdm == null || !rdm.close) //Проверка на вхожение вершины в закрытый список { OpenListValue olv; bool flag = false; if (rdm == null) //(!open.ContainsKey(edge.node_in)) -- Если записи данной вершины нет, создать её с параметрами по-умолчанию { olv = new OpenListValue(edge.Node_in); olv.RealWeight = opn_curr_weight.RealWeight + edge.weight; olv.HeuristicWeight = olv.RealWeight + functionSet.heuristic_between_point(edge.Node_in, node_finish_link); open.Add(edge.Node_in, olv); road_map.Add(edge.Node_in, new RoadInfo(curr, edge)); flag = true; } else { olv = open[edge.Node_in]; if (olv.RealWeight > opn_curr_weight.RealWeight + edge.weight) //Если вес записанный в вершине больше чем новополученный //Сохраняем новые реальные и эвристические веса { //Параметры по-умолчанию безусловно входят в эту ветвь //Удаляем старую эвристу из сортированного списка int index = open_sorted.BinarySearch(olv); while (open_sorted[index] != olv) { index++; } open_sorted.RemoveAt(index); olv.RealWeight = opn_curr_weight.RealWeight + edge.weight; olv.HeuristicWeight = olv.RealWeight + functionSet.heuristic_between_point(edge.Node_in, node_finish_link); rdm.prev = curr; rdm.edge = edge; flag = true; } } //Добавляем еще одну запись в сортированный список с сохранением сортировки if (flag) { int findex = open_sorted.BinarySearch(olv); if (findex < 0) { open_sorted.Insert(~findex, olv); } else { open_sorted.Insert(findex, olv); } } } } } //Если открытый список пуст, то конец алгоритма while (!(open.Count == 0)); //Ecли в маршрутном списке небыла создана запись под финальную точку или она соотве if ((road_map.ContainsKey(node_finish_link) == false)) { return(null); } else { List <EdgeInWork> result = new List <EdgeInWork>(); do { if (road_map[curr].prev == null) { break; } else { result.Add(road_map[curr].edge); curr = road_map[curr].prev; } }while (true); result.Reverse(); return(new Path(result)); } }