高级排序算法

时间:2013-09-17 01:52:47

标签: javascript algorithm google-maps sorting

我正在使用Javascript编写一个使用谷歌地图的应用程序,并根据最近的腿计算一系列腿之间的完整路线。

说我在地图上有4条腿,每条腿都有一个开始和结束纬度和经度。用户指定哪条腿是路线的起点和终点。一条腿的每一端只能连接另一条腿开始。然后那条腿的末端连接到另一条腿开始,依此类推。该代码根据它可以找到的最近的腿确定哪些腿开始连接。

例如这样的东西(虚线是腿):

start-----------end  <-connector->  start----------end  <-connector->  start----------end

我有一个所有腿部坐标的数组,我想对这个数组进行排序,以便它遵循正确的连接进程。然后我可以利用数组通过线性循环生成连接器。

数组看起来像这样:

[
   {start_lat: X, start_lng: X, end_lat: X, end_lng: X},
   {start_lat: X, start_lng: X, end_lat: X, end_lng: X},
]

那些将是内在的腿。然后我将存储在变量中的外腿(两条腿是整个路线的起点和终点):

var start = {end_lat: X, end_lng: X}
var end = {start_lat: X, start_lng: X}

作为一个例子,它可能最终会像:

start -> array[0] -> array[1] -> end

或者它最终会像:

start -> array[1] -> array[0] -> end

算法需要根据起始腿end_lat,end_lng和结束腿end_lat,end_lng对数组进行排序。

最终结果将是一条以最短路径连接在一起的大路。

我正在努力想出一种编写排序算法的方法,该算法考虑了这些独特的因素。

很难把它说成文字,而且我不确定如何帮助它更清晰,但如果我能想到任何有用的东西,我会编辑这篇文章。感谢。

修改:

这是我正在谈论的图片:

map

黑线是腿,红线是我将腿坐标数组排序到正确顺序后需要生成的连接器。生成连接器不是这个算法的一部分,但它只是我想要完成的一个例子,所以你可以理解大局。如您所见,腿之间存在间隙,没有任何坐标重叠。

2 个答案:

答案 0 :(得分:2)

你可以这样做:

DEMO

var start = { end_lat: 1, end_lng: 1 },
    end = { start_lat: 4, start_lng: 4 },
    coordsBetween = [
        { start_lat: 2, start_lng: 2, end_lat: 3, end_lng: 3  },
        { start_lat: 1, start_lng: 1, end_lat: 2, end_lng: 2  },
        { start_lat: 3, start_lng: 3, end_lat: 4, end_lng: 4  }
    ];

function orderedCoords(start, coords) {
    var result = [],
        point = start;

    while (point = coords.filter(function (item) {
        return item.start_lat === point.end_lat
        && item.start_lng === point.end_lng;
    })[0]) {
        result.push(point);
    }   
    return result;
}

console.log(orderedCoords(start, coordsBetween));

基本上我们会发现下一个pointstart结束开始,让point成为下一个start,直到没有匹配为止,在每一步我们推动这一点进入result

编辑:

  

这可以起点和终点的坐标   重叠,但我的没有,他们之间有很大的差距   我需要在它们之间生成“连接器”......

我通过使用algorithm to calculate the closest point寻找重叠坐标来扩展我的第一个想法。

DEMO

var start = { end_lat: 1, end_lng: 1 },
    end = { start_lat: 4, start_lng: 4 },
    segments = [
        { start_lat: 2, start_lng: 2, end_lat: 3, end_lng: 3  },
        { start_lat: 1, start_lng: 1, end_lat: 2, end_lng: 2  },
        { start_lat: 3, start_lng: 3, end_lat: 4, end_lng: 4  }
    ];

function orderedSegments(start, segments) {
    var result = [],
        segment = start,
        i;

    while ((i = indexOfClosestSegment(segment, segments)) !== -1) {
        result.push(segment = segments.splice(i, 1)[0]);
    }

    return result;
}

function indexOfClosestSegment(segment, segments) {
    var i = 0,
        len = segments.length,
        segIndex = -1,
        tempDistance, smallestDistance;

    for (; i < len; i++) {
        if (
            (tempDistance = distanceBetween(segment, segments[i])) < smallestDistance 
            || typeof smallestDistance === 'undefined') {
            smallestDistance = tempDistance;
            segIndex = i;
        }
    }

    return segIndex;        
}

function distanceBetween(segmentA, segmentB) {
    return Math.sqrt(
        Math.pow(segmentB.start_lat - segmentA.end_lat, 2) 
        + Math.pow(segmentB.start_lng - segmentA.end_lng, 2)
    );
}

console.log(orderedSegments(start, segments));
  

请注意,这些点是地理坐标,您需要使用a   球面距离算法,而不是平凡的毕达哥拉斯。我认为通用汽车   为其数据结构提供了这样的辅助函数;当然   该算法仍然可以使用不同的distanceBetween   实现。 - @Bergi

答案 1 :(得分:0)

我认为DFS是好的并且将访问的有序腿列表转移到下一个递归。 并且在每次递归中选择最后一条腿,并对每条未经检查的腿进行递归。