我要实现的是使用Hamiltonian path的backtracking algorithm查找程序。
注意: 尽管我设法找到的大多数数学论文和SO主题都与回答“是否是哈密顿量”这个问题有关 路径/周期”存在或专门用于查找哈密顿量周期,这是我的问题 稍有不同-我需要找出顶点的顺序, 哈密顿量路径通过
我建立了以下表示形式的邻接矩阵(顶点从1开始索引)
const vertexes = [ { vertex: 1, peers: [ 3, 8, 15 ] },
{ vertex: 2, peers: [ 7, 14, 23 ] },
{ vertex: 3, peers: [ 1, 6, 13, 22 ] },
{ vertex: 4, peers: [ 5, 12, 21 ] },
{ vertex: 5, peers: [ 4, 11, 20 ] },
{ vertex: 6, peers: [ 3, 10, 19 ] },
{ vertex: 7, peers: [ 2, 9, 18 ] },
{ vertex: 8, peers: [ 1, 17 ] },
{ vertex: 9, peers: [ 7, 16 ] },
{ vertex: 10, peers: [ 6, 15 ] },
{ vertex: 11, peers: [ 5, 14 ] },
{ vertex: 12, peers: [ 4, 13 ] },
{ vertex: 13, peers: [ 3, 12, 23 ] },
{ vertex: 14, peers: [ 2, 11, 22 ] },
{ vertex: 15, peers: [ 1, 10, 21 ] },
{ vertex: 16, peers: [ 9, 20 ] },
{ vertex: 17, peers: [ 8, 19 ] },
{ vertex: 18, peers: [ 7 ] },
{ vertex: 19, peers: [ 6, 17 ] },
{ vertex: 20, peers: [ 5, 16 ] },
{ vertex: 21, peers: [ 4, 15 ] },
{ vertex: 22, peers: [ 3, 14 ] },
{ vertex: 23, peers: [ 2, 13 ] } ]
接下来,从顶点18作为根和paths
数组开始,其中包含单个路径[[18]]
,我尝试对该数组进行更改,将其替换为保存原始路由的临时副本(如果没有死,结束),直到找不到潜在的长度为n
(顶点总数)的路由或路径:
while(paths.length>0){
let tempPath = [];
for(path of paths){
const nextSteps = vertexes.find(({vertex}) => vertex == path[path.length-1]).peers.filter(v => !path.includes(v));
if(!nextSteps.length) continue;
else if(path.length == n-1) return [...path, nextSteps[0]];
else nextSteps.forEach(step => tempPath.push([...path,step]));
}
paths = tempPath;
}
因此,问题在于上述代码永远不会退出循环,也永远不会返回所需的输出([18, 7, 9, 16, 20, 5, 11, 14, 22, 3, 1, 8, 17, 19, 6, 10, 15, 21, 4, 12, 13, 23, 2]
)。
对于上述代码为何失败以及如何修复该代码以返回预期输出的想法,将不胜感激。
编辑:由于@DavidSampson和@trincot指出了我的拼写错误,因此我的代码现在可以正常工作了:
while(paths.length>0){
let tempPath = [];
for(let path of paths){
const nextSteps = vertexes.find(({vertex}) => vertex == path[path.length-1]).peers.filter(v => !path.includes(v));
if(!nextSteps.length) continue;
else if(path.length == n-1) return [...path, nextSteps[0]];
else tempPath.push(...nextSteps.map(v => [...path,v]));
}
paths = tempPath;
}
现在性能是我最关心的问题,关于如何改善性能有什么建议吗?
答案 0 :(得分:2)
主要问题是拼写错误,如果您使用严格模式,则可以避免该错误:
更改:
path = tempPath;
收件人:
paths = tempPath;
还要声明您的变量。就像这里:
for (let path of paths) {
// ^^^^
然后它对我有用:
"use strict";
function hamiltonian(vertexes, start) {
let n = vertexes.length;
let paths = [[start]];
while(paths.length>0) {
let tempPath = [];
for(let path of paths){
const nextSteps = vertexes.find(({vertex}) => vertex == path[path.length-1]).peers.filter(v => !path.includes(v));
if(!nextSteps.length) continue;
else if(path.length == n-1) return [...path, nextSteps[0]];
else nextSteps.forEach(step => tempPath.push([...path,step]));
}
paths = tempPath;
}
}
const vertexes = [ { vertex: 1, peers: [ 3, 8, 15 ] },{ vertex: 2, peers: [ 7, 14, 23 ] },{ vertex: 3, peers: [ 1, 6, 13, 22 ] },{ vertex: 4, peers: [ 5, 12, 21 ] },{ vertex: 5, peers: [ 4, 11, 20 ] },{ vertex: 6, peers: [ 3, 10, 19 ] },{ vertex: 7, peers: [ 2, 9, 18 ] },{ vertex: 8, peers: [ 1, 17 ] },{ vertex: 9, peers: [ 7, 16 ] },{ vertex: 10, peers: [ 6, 15 ] },{ vertex: 11, peers: [ 5, 14 ] },{ vertex: 12, peers: [ 4, 13 ] },{ vertex: 13, peers: [ 3, 12, 23 ] }, { vertex: 14, peers: [ 2, 11, 22 ] },{ vertex: 15, peers: [ 1, 10, 21 ] },{ vertex: 16, peers: [ 9, 20 ] },{ vertex: 17, peers: [ 8, 19 ] },{ vertex: 18, peers: [ 7 ] },{ vertex: 19, peers: [ 6, 17 ] },{ vertex: 20, peers: [ 5, 16 ] },{ vertex: 21, peers: [ 4, 15 ] },{ vertex: 22, peers: [ 3, 14 ] },{ vertex: 23, peers: [ 2, 13 ] } ];
let result = hamiltonian(vertexes, 18);
console.log('result', result);
请注意,使用动态编程可以缩短运行时间。在Hamiltonian path problem上查看不同的方法。