JavaScript数组对于c-w保存算法来说太小了,怎么办?

JavaScript数组对于c-w保存算法来说太小了,怎么办?,javascript,algorithm,Javascript,Algorithm,我正在实现-w保存算法。 我实现了它,并在小型设备上进行了测试,效果非常好。但是当我输入大数据时,保存函数中出现了一个问题,它计算 c(i,j) = c(start,i) + c(start,j) - c(i,j) 其中c(i,j)是从i到j的旅行成本。 所以我必须先计算,但结果是非常大的计算,我想这需要时间,因为我的数据中有9000多个位置 9000+8999+ ...... +1 = 50,000,000 (near to that) 步骤 这是我计算储蓄的函数 t

我正在实现-w保存算法。 我实现了它,并在小型设备上进行了测试,效果非常好。但是当我输入大数据时,保存函数中出现了一个问题,它计算

   c(i,j) = c(start,i) + c(start,j) - c(i,j)
其中c(i,j)是从i到j的旅行成本。 所以我必须先计算,但结果是非常大的计算,我想这需要时间,因为我的数据中有9000多个位置

        9000+8999+ ...... +1 = 50,000,000 (near to that)
步骤

这是我计算储蓄的函数

this.calc_savings=function()
{
    var size = this.city_array.length;  //number of cities: greater than 9000 

    var start =start_city_index;
    for(var i=0; i < size; i ++)
    {
        if(i != start)
        {
            for(var j=i+1; j< size ; j++)
            {
                if(j !=start)
                {

                    var dis1 = this.get_distance(start,i); 
                    var dis2 = this.get_distance(start,j);
                    var dis3 = this.get_distance(j,i);

                    var cost = dis1 + dis2 - dis3;
                    var m_save = new saving(i,j,cost);
                    this.savings.push(m_save);
                  }

              }
          }

      }
  };
功能,工作速度快。 该函数计算两个地球坐标之间的距离,如图所示

      function calcCrow(lat1, lon1, lat2, lon2) 
      { 
       var lati, latj, longi, longj;
       var q1, q2, q3, q4, q5;
       var m_pi = 3.14159265358979323846264; 
       lati = m_pi * lat1 / 180.0;
       latj = m_pi * lat2 / 180.0;

       longi = m_pi * lon1 / 180.0;
       longj = m_pi * lon2 / 180.0;

       q1 = Math.cos (latj) * Math.sin(longi - longj);
       q3 = Math.sin((longi - longj)/2.0);
       q4 = Math.cos((longi - longj)/2.0);

       q2 = Math.sin(lati + latj) * q3 * q3 - Math.sin(lati - latj) * q4 * q4;
       q5 = Math.cos(lati - latj) * q4 * q4 - Math.cos(lati + latj) * q3 * q3;

       var dis_meter =  (6378388.0 * Math.atan2(Math.sqrt(q1*q1 + q2*q2), q5) + 1.0);
       return dis_meter / 1000;
       };
被称为

   this.get_distance=function(first,next)
   {
     var first_city,next_city;
     first_city = this.city_array[first];
     next_city = this.city_array[next];


    return   Math.floor(calcCrow(first_city.x, first_city.y, next_city.x, next_city.y));

    };
保存定义为

     var saving = function( x_int, y_int,value) 
     {
      this.x =x_int ;   //latitude
      this.y =y_int ;   //longitude
      this.value = value; 
     };
那么,我该怎么办


有什么建议吗?

您可以通过简单地缓存结果,大大减少对
get\u distance
的调用量,因为我假设这些值在一个循环中不会改变

this.calc_savings = function(){
    var size = this.city_array.length;  //number of cities: greater than 9000 

    var startDistances = this.city_array.map((city,i) => i === start_city_index? 0: this.get_distance(start_city_index, i));

    for(var i=0; i < size; ++i){
        if(i === start_city_index) continue;
        var dis1 = startDistances[i];

        for(var j=i+1; j<size; ++j){
            if(j === start_city_index) continue;

            var dis2 = startDistances[j];
            var dis3 = this.get_distance(j, i);
            var cost = dis1 + dis2 - dis3;
            this.savings.push(new saving(i, j, cost));
        }
    }
  };

通过简单地缓存结果,您可以大大减少对
get\u distance
的调用量,因为我假设这些值在一个循环中不会改变

this.calc_savings = function(){
    var size = this.city_array.length;  //number of cities: greater than 9000 

    var startDistances = this.city_array.map((city,i) => i === start_city_index? 0: this.get_distance(start_city_index, i));

    for(var i=0; i < size; ++i){
        if(i === start_city_index) continue;
        var dis1 = startDistances[i];

        for(var j=i+1; j<size; ++j){
            if(j === start_city_index) continue;

            var dis2 = startDistances[j];
            var dis3 = this.get_distance(j, i);
            var cost = dis1 + dis2 - dis3;
            this.savings.push(new saving(i, j, cost));
        }
    }
  };

是什么让你认为JavaScript数组不能容纳100000个元素?我认为真正的问题是你正在实现的算法的预期运行时间与元素数量的平方成正比。这在任何编程环境中都需要一段时间。数组的最大长度是2^32-1,对于大多数用例来说应该足够了?@Teemu刚刚测试了一个数组。似乎我的程序如此缓慢的真正原因是“get_distance”,它计算两个坐标之间的距离。但我无法避免计算这些,我必须这样做somewhere@alim您的
getDistance()
代码是什么样子的?有时,在某些算法中,处理距离的平方和处理实际距离一样好,这节省了平方根计算。(但你不能总是这么做。)是什么让你认为JavaScript数组不能容纳100000个元素?我认为真正的问题是,你正在实现的算法的预期运行时间与元素数量的平方成正比。这在任何编程环境中都需要一段时间。数组的最大长度是2^32-1,对于大多数用例来说应该足够了?@Teemu刚刚测试了一个数组。似乎我的程序如此缓慢的真正原因是“get_distance”,它计算两个坐标之间的距离。但我无法避免计算这些,我必须这样做somewhere@alim您的
getDistance()
代码是什么样子的?有时,在某些算法中,处理距离的平方和处理实际距离一样好,这节省了平方根计算。(但你不能总是这么做。)我加入了这些代码并阅读了你的答案以理解它第三行计算从起点到其他城市的所有距离,然后再使用它,我得到了。谢谢如果你能教我更多可能的改进,那就太好了。我包括了这些代码并阅读了你的答案以理解它。:)第三行计算从起点到其他城市的所有距离,然后再使用它,我得到了。谢谢如果你能教我更多可能的改进,那就太好了。
//Beware, code is untested
this.init_cache = function(){
    var rad = Math.PI / 180;
    var size = this.city_array.length;
    var _distances = this._distances = Array(size * (size-1) / 2);
    var _offsets = this._offsets = Array(size);

    for(var i = 0, k = 0; i<size; ++i){
        _offsets[i] = k;
        var a = this.city_array[i],
            lat1 = a.x * rad, 
            lon1 = a.y * rad;

        for(var j = i+1; j<size; ++j){
            var b = this.city_array[j],
                lat2 = b.x * rad, 
                lon2 = b.y * rad,

                q1 = Math.cos(lat2) * Math.sin(lon1 - lon2),
                q3 = Math.sin((lon1 - lon2)/2),
                q4 = Math.cos((lon1 - lon2)/2),

                q2 = Math.sin(lat1 + lat2) * q3*q3 - Math.sin(lat1 - lat2) * q4*q4,
                q5 = Math.cos(lat1 - lat2) * q4*q4 - Math.cos(lat1 + lat2) * q3*q3,

                dist = 6378388 * Math.atan2(Math.sqrt(q1*q1 + q2*q2), q5) + 1;

            _distances[k++] = Math.floor( dist / 1000 );
        }
    }
};

this.get_distance = function(i, j){
    if(i === j) return 0;
    if(j < i) i^=j, j^=i, i^=j; //swap i and j
    this._distances || this.init_cache(); //just ensuring that cache is initialized when using it.
    return this._distances[ this._offsets[i] + j-i-1 ]
};

this.calc_savings = function(){
    var size = this.city_array.length;
    for(var i = 0; i < size; i ++){
        if(i === start_city_index) continue;
        var dis1 = this.get_distance(start_city_index,i); 

        for(var j = i+1; j < size; j++){
            if(j === start_city_index) continue;

            var dis2 = this.get_distance(start_city_index,j);
            var dis3 = this.get_distance(j,i);
            var cost = dis1 + dis2 - dis3;

            this.savings.push(new saving(i,j,cost));
        }

    }
};