- 把图看成以起点为根节点的树状图
- 使用深度遍历算法遍历路径
- 遍历到节点为目标节点时,保存这条路径
find2PointsPath(sourceId, targetId) {
const { nodesKV } = this.chart.getStore(); // 节点集合
let pathArr = []; // 保存找到的所有路径
/**
*
* @param {string} sourceId 当前节点 id,每次递归会改变
* @param {string} targetId 目标节点 id
* @param {array} pathNodes 当前查找路径的所有节点 id
*/
const findPath = (sourceId, targetId, pathNodes = []) => {
pathNodes = [...pathNodes]; // 存储当前路径的节点 id。拷贝一下,避免引用传递导致递归调用时相互影响。
pathNodes.push(sourceId);
// 找到终点,保存路径退出
if (sourceId === targetId) {
pathArr.push(pathNodes);
return;
}
// 取出当前节点
const node = nodesKV[sourceId];
// 通过当前节点取出相邻的节点
const neighborNodes = { ...gof(node, {})('childrenKV')(), ...gof(node, {})('parentsKV')() };
// 遍历相邻节点继续查找
for (let id in neighborNodes) {
// 没在当前查找路径中的才递归继续查找,避免图中的环导致死循环
// 比如 A-B, A-C, B-C 这样的关系,我们从 A 找到 B,从 B 找到 C,pathNodes 中有 [A, B],然后从 C 找,A 和 B 都是 C 的相邻节点,如果不排除 pathNodes 中的节点必然陷入死循环
if (!pathNodes.includes(id)) {
findPath(id, targetId, pathNodes);
}
}
};
// 开始查找
findPath(sourceId, targetId);
// 路径长度由短到长排序
pathArr.sort((path1, path2) => {
return path1.length - path2.length;
});
return pathArr;
}