简介
网上看到很多最短路径求解问题的js实现版本,看了老半天,没怎么看懂。
看懂了我也复现不了。+_+!
所以自己写了个简单易懂的,小白容易看懂
。
至于大佬,,,,觉得写的不好你来打我咯。。。
别看代码长,一大半是测试代码
题目
- 已知图如下,所有线段可以来回走,求 A 到 G 最短路线
- 已知图如下,所有线段可以来回走,求 A 到 K 最短路线
es6实现
- 如果有多个长度相同的最短路径,只输出
第一个
最短路径
class Graph {
constructor(nodes) {
this.nodes = nodes;//保存所有节点
this.line = {};//保存所有节点关系
this.res = [];//最短路径结果
this.hasRes = false;//是否 至少有一个可以到达的路径
}
addLine(v, w) {
this._addLine(v, w);
this._addLine(w, v);
}
_addLine(v, w) {
!this.line[v] && (this.line[v] = []);
this.line[v].push(w);
}
minPath(v, w) {
this.step(this.line[v], [v], w);
return this.res;
}
step(adjacentNodes, tempRes, w) {
//当前节点没有相邻节点
if (!adjacentNodes) {
return;
}
//存在可以到达的路径,并且比正在探测的路径短则直接退出探测
if (this.hasRes && this.res.length < tempRes.length) {
return;
}
adjacentNodes.forEach(item => {
//当前探测的点已经走过了,不再重复走
if (tempRes.indexOf(item) !== -1) {
return;
}
let newTempRes = tempRes.concat(item);
//到达终点
if (item === w) {
if (this.hasRes) {
if (newTempRes.length < this.res.length) {
//已有最短路径,且比当前路径更短,替换
this.res = newTempRes;
}
} else {
//目前没有最短路径,替换
this.res = newTempRes;
this.hasRes = true;
}
} else {
this.step(this.line[item], newTempRes, w);
}
});
}
toString() {
console.log("数据结构:");
console.log(this.nodes);
console.log("===================");
console.log(this.line);
}
}
//测试
let graph = new Graph(["A", "B", "C", "D", "E", "F", "G", "H"]);
graph.addLine("A", "C");
graph.addLine("B", "A");
graph.addLine("B", "H");
graph.addLine("B", "C");
graph.addLine("F", "H");
graph.addLine("B", "E");
graph.addLine("E", "H");
graph.addLine("C", "D");
graph.addLine("D", "E");
graph.addLine("G", "E");
graph.addLine("E", "C");
graph.addLine("E", "F");
graph.addLine("G", "F");
graph.toString();
console.log("结果:");
console.log(graph.minPath("A", "G")); //[ 'A', 'C', 'E', 'G' ]
let graph1 = new Graph(["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]);
graph1.addLine("A", "B");
graph1.addLine("A", "C");
graph1.addLine("H", "A");
graph1.addLine("D", "A");
graph1.addLine("B", "C");
graph1.addLine("E", "B");
graph1.addLine("B", "F");
graph1.addLine("D", "G");
graph1.addLine("J", "K");
graph1.addLine("F", "L");
graph1.addLine("E", "I");
graph1.addLine("E", "F");
graph1.addLine("C", "D");
graph1.addLine("C", "F");
graph1.addLine("F", "G");
graph1.addLine("K", "L");
graph1.addLine("G", "H");
graph1.addLine("G", "L");
graph1.addLine("I", "J");
graph1.toString();
console.log("结果:");
console.log(graph1.minPath("A", "K")); //[ 'A', 'B', 'F', 'L', 'K' ]
- 如果有多个长度相同的最短路径,输出
所有
最短路径
class Graph {
constructor(nodes) {
this.nodes = nodes;//保存所有节点
this.line = {};//保存所有节点关系
this.res = [];//最短路径结果
this.hasRes = false;//是否 至少有一个可以到达的路径
}
addLine(v, w) {
this._addLine(v, w);
this._addLine(w, v);
}
_addLine(v, w) {
!this.line[v] && (this.line[v] = []);
this.line[v].push(w);
}
minPath(v, w) {
this.step(this.line[v], [v], w);
return this.res;
}
step(adjacentNodes, tempRes, w) {
//当前节点没有相邻节点
if (!adjacentNodes) {
return;
}
//存在可以到达的路径,并且比正在探测的路径短则直接退出探测
if (this.hasRes && this.res[0].length < tempRes.length) {
return;
}
adjacentNodes.forEach(item => {
//当前探测的点已经走过了,不再重复走
if (tempRes.indexOf(item) !== -1) {
return;
}
let newTempRes = tempRes.concat(item);
//到达终点
if (item === w) {
if (this.hasRes) {
if (newTempRes.length < this.res[0].length) {
//已有最短路径,且比当前路径更短,替换
this.res = [newTempRes];
}else if(newTempRes.length == this.res[0].length){
//已有最短路径,且长度相同,添加
this.res.push(newTempRes);
}
} else {
//目前没有最短路径,替换
this.res = [newTempRes];
this.hasRes = true;
}
} else {
this.step(this.line[item], newTempRes, w);
}
});
}
toString() {
console.log("数据结构:");
console.log(this.nodes);
console.log("===================");
console.log(this.line);
}
}
//测试
let graph = new Graph(["A", "B", "C", "D", "E", "F", "G", "H"]);
graph.addLine("A", "C");
graph.addLine("B", "A");
graph.addLine("B", "H");
graph.addLine("B", "C");
graph.addLine("F", "H");
graph.addLine("B", "E");
graph.addLine("E", "H");
graph.addLine("C", "D");
graph.addLine("D", "E");
graph.addLine("G", "E");
graph.addLine("E", "C");
graph.addLine("E", "F");
graph.addLine("G", "F");
graph.toString();
console.log("结果:");
console.log(graph.minPath("A", "G"));
// [ [ 'A', 'C', 'E', 'G' ], [ 'A', 'B', 'E', 'G' ] ]
let graph1 = new Graph(["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]);
graph1.addLine("A", "B");
graph1.addLine("A", "C");
graph1.addLine("H", "A");
graph1.addLine("D", "A");
graph1.addLine("B", "C");
graph1.addLine("E", "B");
graph1.addLine("B", "F");
graph1.addLine("D", "G");
graph1.addLine("J", "K");
graph1.addLine("F", "L");
graph1.addLine("E", "I");
graph1.addLine("E", "F");
graph1.addLine("C", "D");
graph1.addLine("C", "F");
graph1.addLine("F", "G");
graph1.addLine("K", "L");
graph1.addLine("G", "H");
graph1.addLine("G", "L");
graph1.addLine("I", "J");
graph1.toString();
console.log("结果:");
console.log(graph1.minPath("A", "K"));
// [ [ 'A', 'B', 'F', 'L', 'K' ],
// [ 'A', 'C', 'F', 'L', 'K' ],
// [ 'A', 'H', 'G', 'L', 'K' ],
// [ 'A', 'D', 'G', 'L', 'K' ] ]
- 单向图
addLine(v, w) {
this._addLine(v, w);
// this._addLine(w, v);//只需要将这一行注释掉就是单向图的实现。
// 注:当前测试用例单向图没有合法路径
}
写完了, 就酱~
点个赞再走咯 +_+