Входные данные graph являются DAG и выглядят так:
+-----------------------+
| |
| v
Paris -> Bruxelles -> Amsterdam -> Berlin
| ^
| |
+-----------------------+
Мы можем построить объект с исходными строками, сопоставленными с массивом их возможныхадресаты, которые намного удобнее использовать, чем входной объект, затем запустите DFS на графике и получите каждый путь к результату.
function *findPaths(graph, src, dst, path=[]) {
if (src === dst) {
yield path.concat(dst);
}
else if (graph[src]) {
path.push(src);
for (const neighbor of graph[src]) {
yield *findPaths(graph, neighbor, dst, path, visited);
}
path.pop(src);
}
};
const graphify = routes => {
const graph = {};
for (const node of routes) {
if (!graph[node.V1]) {
graph[node.V1] = [];
}
graph[node.V1].push(node.V2)
}
return graph;
};
const routes = [
{ HD: '9:20', V1: 'Paris', V2: 'Amsterdam', D: '3:20' },
{ HD: '8:30', V1: 'Paris', V2: 'Bruxelles', D: '1:20' },
{ HD: '10:00', V1: 'Bruxelles', V2: 'Amsterdam', D: '2:10' },
{ HD: '12:30', V1: 'Amsterdam', V2: 'Berlin', D: '6:10' },
{ HD: '11:30', V1: 'Bruxelles', V2: 'Berlin', D: '9:20' }
];
console.log(...findPaths(graphify(routes), "Paris", "Berlin"));
Если вы ожидаете циклы на своем графике, добавьте Set
, чтобы отслеживать посещенные узлы, чтобы избежать повторного посещения их во время обхода:
function *findPaths(graph, src, dst, path=[], visited=(new Set())) {
if (src === dst) {
yield path.concat(dst);
}
else if (graph[src] && !visited.has(src)) {
visited.add(src);
path.push(src);
for (const neighbor of graph[src]) {
yield *findPaths(graph, neighbor, dst, path, visited);
}
visited.delete(src);
path.pop(src);
}
};
const graphify = routes => {
const graph = {};
for (const node of routes) {
if (!graph[node.V1]) {
graph[node.V1] = [];
}
graph[node.V1].push(node.V2)
}
return graph;
};
const routes = [
{ HD: '9:20', V1: 'Paris', V2: 'Amsterdam', D: '3:20' },
{ HD: '8:30', V1: 'Paris', V2: 'Bruxelles', D: '1:20' },
{ HD: '10:00', V1: 'Bruxelles', V2: 'Amsterdam', D: '2:10' },
{ HD: '12:30', V1: 'Amsterdam', V2: 'Paris', D: '6:10' },
{ HD: '12:30', V1: 'Amsterdam', V2: 'Berlin', D: '6:10' },
{ HD: '11:30', V1: 'Bruxelles', V2: 'Berlin', D: '9:20' },
{ HD: '11:30', V1: 'Bruxelles', V2: 'Paris', D: '9:20' }
];
console.log(...findPaths(graphify(routes), "Paris", "Berlin"));
Если вы хотите учесть время в пути (вес ребер), используйте Алгоритм Дейкстры . Реализация более сложна, потому что нам нужна очередь приоритетов (min / Fibonacci heap) для эффективного извлечения кратчайшего пробного расстояния.