Javascript 存储地址列表中可能的旅行路径
我有一个地址列表,我们可以称之为a-Z。我使用谷歌地图api对这些地址进行地理编码,然后找到它们之间的旅行时间,得到一个26x26矩阵。我想提出一个函数,它接受地址列表、矩阵、目标节点(我将调用@)和时间限制,并返回所有可能的旅行路径的列表,这些路径可以从a到@到任意数量的不同、不重复的目的地,然后在到达时间限制之前返回a 我认为递归函数可能是实现这一点的最佳方法,但我只从理论上了解了它们,不知道它是否有效 到目前为止,我的想法是这样的:Javascript 存储地址列表中可能的旅行路径,javascript,recursion,Javascript,Recursion,我有一个地址列表,我们可以称之为a-Z。我使用谷歌地图api对这些地址进行地理编码,然后找到它们之间的旅行时间,得到一个26x26矩阵。我想提出一个函数,它接受地址列表、矩阵、目标节点(我将调用@)和时间限制,并返回所有可能的旅行路径的列表,这些路径可以从a到@到任意数量的不同、不重复的目的地,然后在到达时间限制之前返回a 我认为递归函数可能是实现这一点的最佳方法,但我只从理论上了解了它们,不知道它是否有效 到目前为止,我的想法是这样的: var duration = 0; var path =
var duration = 0;
var path = [];
function getPath(addList, matrix, targetNode, currentNode, timeLimit){
if(duration+matrix[matrix.indexOf(currentNode), matrix.indexOf(A)]>=timeLimit{
path[path.length-1] = A;
// (1) add path to the list of possible paths
}
else{
var tempList = addList;
tempList.splice(tempList.indexOf(currentNode), 1);
for(int i = 0; i < tempList.length; i++){
// (2) increase duration by matrix[matrix.indexOf(currentNode), matrix.indexOf(tempList[i])];
getPath(tempList, matrix, targetNode, tempList[i], timeLimit);
}
}
}
var partialPaths = [A],
nodes = [/*this contains all of your nodes*/],
paths = [],
maxDistance = totalDistance - distance([A@]),
//max distance of any path between A and @
currentPath;
while(partialPaths.length > 0){
currentPath = partialPaths.pop();
paths.push(currentPath.concat([@]); //Adds the current path plus @
nodes.forEach(function(node){
if(distance(currentPath + node + @) < maxDistance &&
(node not in current path){
partialPaths.push(currentPath + node);
}
});
}
我可以推到它并在每次函数调用时引用它。您可以通过创建一个到目标的所有路径的数组来做到这一点,该数组的距离小于最大允许距离减去到目标的最短路径的距离 我将分两步进行:
首先,遍历并计算从每个节点到目标的最短路径。在节点上保存每条最短路径及其距离 计算完所有最短路径后,就可以开始创建可能的部分路径数组和可能的路径数组。作为可能的部分路径,路径的总距离加上从路径中最后一个节点到目标的最短路径距离小于最大路径长度。可能的路径是从
a
到@
的小于最大路径长度的路径
您可以遍历可能的部分路径数组,在每个步骤中删除第一个可能的部分路径,对于您可以从当前节点移动到的所有节点,检查将该节点添加到当前路径是否是可能的部分路径。如果是,请将其添加到可能的部分路径数组中。”“您可以前往的节点”表示您尚未访问的、连接到当前节点的节点
现在,看起来所有节点都已连接到所有其他节点。这可能会有问题,因为它提供了从a
到@
的最大可能路径4.0329146e+26(也称为26!)。通常,对于这些类型的问题,您将节点限制为仅可连接到附近的节点,以避免太多的缩放问题,但仍可能生成大量的路径。所有可能的路径都可能是大量的
我建议您不要使用递归,因为您正在生成大量内容的列表。只需创建一个可能性数组,并不断从中删除内容/向其中添加内容,直到其为空
编辑:由于您的所有节点都连接到其他所有节点,因此可以从任何可能的潜在路径,通过添加目标节点来创建路径。这就简化了查找路径的过程
为了找到可能的路径,考虑任何可能的路径是另一个可能的路径加上一个节点。如果您知道ABC是一个可能的路径,那么可以检查ABCD、ABCE、ABCF等,并将ABC@添加到半路径数组中
同样,如果ABD不是可能的路径,则不需要考虑从该路径开始的任何其他路径。要找到从A到@的所有路径,可以从数组
[A]
开始
您的函数如下所示:
var duration = 0;
var path = [];
function getPath(addList, matrix, targetNode, currentNode, timeLimit){
if(duration+matrix[matrix.indexOf(currentNode), matrix.indexOf(A)]>=timeLimit{
path[path.length-1] = A;
// (1) add path to the list of possible paths
}
else{
var tempList = addList;
tempList.splice(tempList.indexOf(currentNode), 1);
for(int i = 0; i < tempList.length; i++){
// (2) increase duration by matrix[matrix.indexOf(currentNode), matrix.indexOf(tempList[i])];
getPath(tempList, matrix, targetNode, tempList[i], timeLimit);
}
}
}
var partialPaths = [A],
nodes = [/*this contains all of your nodes*/],
paths = [],
maxDistance = totalDistance - distance([A@]),
//max distance of any path between A and @
currentPath;
while(partialPaths.length > 0){
currentPath = partialPaths.pop();
paths.push(currentPath.concat([@]); //Adds the current path plus @
nodes.forEach(function(node){
if(distance(currentPath + node + @) < maxDistance &&
(node not in current path){
partialPaths.push(currentPath + node);
}
});
}
var partialPaths=[A],
nodes=[/*这包含所有节点*/],
路径=[],
maxDistance=总距离-距离([A@]),
//和之间任意路径的最大距离@
电流通路;
而(部分路径长度>0){
currentPath=partialPath.pop();
path.push(currentPath.concat([@]);//添加当前路径加@
forEach(函数(节点){
如果(距离(当前路径+节点+@)
在此之后,您将拥有一个从A到@的所有路径的数组。只需将每个路径与长度小于总长度减去最大长度的所有路径组合,即可获得所有往返路径。您或多或少地在搜索这样的内容:用户可以在往返途中重复目的地,还是只能重复目的地一次访问一次?@ckersch每次仅访问一次“首先,遍历并计算从每个节点到目标的最短路径。将每个最短路径及其距离保存在节点上。”“从每个节点到目标的最短路径不是直接路径吗?它包含在矩阵变量中。同时,虽然我同意理论上不是这样这里是26个组合,在实际应用中,我正在构建的应用程序没有路径将远远超过6个节点,并且由于节点间旅行时间和最大旅行时间,肯定不会超过8个。无论哪种方式,你能详细说明最后一点吗?谢谢!我忘了所有东西都与其他所有东西相连,所以是的,所有东西上的最短路径都是直接到目标的,这会简化很多事情。递归的危险在于,你最终会为你的每一层创建一个函数实例,如果你先去深度,然后为每一条路径创建一个实例。因为你不想存储所有这些,所以没有令人信服的理由o最后保存所有结果。那么,什么是更好的方法呢?我不知道如何循环所有选项并跟踪我在组合中的位置。最终,每个节点都会有权重,并且会包含容量限制,但我正在使用最简单的方法,不幸的是,这意味着执行most计算。只有26个选项,生成整个集合对我来说不是太不合理。计算时间不太重要,因为此应用程序将替换的过程需要大约一个小时或更多的人力资源