允许插值的稀疏有序二维浮点数组的最佳数据结构(perl)

允许插值的稀疏有序二维浮点数组的最佳数据结构(perl),perl,data-structures,Perl,Data Structures,数据是股票期权。我想根据到期日(int)和货币的标准化距离(float)创建一个2D数组,值是标准化出价和要价的列表。如果所需的元素不在数组中,我希望能够在最近的元素之间进行插值 我看到3种可能的数据结构: 一个稀疏的2D数组,可能有10000个元素,可能有1/3的空间 二维链表,即:每个数据元素有4个列表指针(因此3000个元素变为15000个) 一个2D散列(可能有3000个元素),每个维度中有2个键的排序列表(每个键可能有100个元素) 主要问题是需要插值时的有效检索。 使用任何方法检索现

数据是股票期权。我想根据到期日(int)和货币的标准化距离(float)创建一个2D数组,值是标准化出价和要价的列表。如果所需的元素不在数组中,我希望能够在最近的元素之间进行插值

我看到3种可能的数据结构:

  • 一个稀疏的2D数组,可能有10000个元素,可能有1/3的空间

  • 二维链表,即:每个数据元素有4个列表指针(因此3000个元素变为15000个)

  • 一个2D散列(可能有3000个元素),每个维度中有2个键的排序列表(每个键可能有100个元素)

  • 主要问题是需要插值时的有效检索。 使用任何方法检索现有元素都相对简单

    我目前正在使用选项3,但检索有点麻烦,因为我必须沿着每个维度的键列表扫描,直到找到占用的元素,然后进行2路或4路插值。 我使用moreUtils::firstindx($\u>$desiredKey)来查找键。链接列表(选项2)将省去我对键列表数组的搜索

    选项1还需要扫描,不需要键列表查找的初始步骤,但可能需要查看更多的空单元格。插入将是一个真正的麻烦

    我会做比插入更多的搜索


    有没有人对最有效的数据结构有什么建议。

    由于主要是按寿命进行查找,按距离进行查找,很少插入,因此我会使用排序数组通过二进制搜索查找记录

    • 查找现有元素:O(日志N)
    • 查找缺少元素的框:O(日志N)
    • 插入:O(N)
    鉴于

    my @data = (
       [ $lifespan0, $distance0, $bid0, $ask0 ],
       [ $lifespan1, $distance1, $bid1, $ask1 ],
       ...
    );
    
    my $lifespan_search_cmp = sub { $a <=> $data[$b][0] };
    my $distance_search_cmp = sub { $a <=> $data[$b][1] };
    
    插入:

    my $i = binsearch_first \&$lifespan_search_cmp, $lifespan, @by_lifespan;
    my $j = binsearch_first \&$distance_search_cmp, $distance, @by_distance;
    
    push @data, [ $lifespan, $distance , $bid, $ask ];
    
    splice(@by_lifespan, $i >= 0 ? $i : ~$i, 0, $#data);
    splice(@by_distance, $j >= 0 ? $j : ~$j, 0, $#data);
    
    潜艇:

    sub-bin首先搜索(&$\@){
    我的$compare=$\u0];
    #我的$value=$\u1];
    my$array=$\u2];
    我的$min=0;
    我的$max=$#$数组;
    如果$max==-1,则返回-1;
    my$ap=do{no strict'refs';\*{caller().::a'}};local*$ap;
    my$bp=do{no strict'refs';\*{caller().::b'}};local*$bp;
    *$ap=\($\[1]);
    而($min[$mid]);
    my$cmp=$compare->();
    如果($cmp<0){
    $max=$mid-1;
    }
    elsif($cmp>0){
    $min=$mid+1;
    }
    否则{
    如果$mid==$min,则返回$mid;
    $max=$mid;
    }
    }
    #将无符号整数转换为有符号整数。
    退回拆包('j',包装('j',~$min));
    }
    子对象向前运行(&$\@){
    我的$compare=$\u0];
    #我的$value=$\u1];
    我的$start=$\u2];
    my$array=$\u3];
    如果$start<0,则返回;
    my$ap=do{no strict'refs';\*{caller().::a'}};local*$ap;
    my$bp=do{no strict'refs';\*{caller().::b'}};local*$bp;
    *$ap=\($\[1]);
    我的$i=$start;
    而($i[$i]);
    my$cmp=$compare->()
    最后,;
    ++$i;
    }
    返回wantarray?($start..$i-1):$i-1;
    }
    

    您可能希望在浮点比较(即在
    $distance\u search\u cmp
    中)中使用容差。

    由于您主要按寿命执行查找,按距离执行查找,并且插入很少,因此我会使用排序数组按二进制搜索查找记录

    • 查找现有元素:O(日志N)
    • 查找缺少元素的框:O(日志N)
    • 插入:O(N)
    鉴于

    my @data = (
       [ $lifespan0, $distance0, $bid0, $ask0 ],
       [ $lifespan1, $distance1, $bid1, $ask1 ],
       ...
    );
    
    my $lifespan_search_cmp = sub { $a <=> $data[$b][0] };
    my $distance_search_cmp = sub { $a <=> $data[$b][1] };
    
    插入:

    my $i = binsearch_first \&$lifespan_search_cmp, $lifespan, @by_lifespan;
    my $j = binsearch_first \&$distance_search_cmp, $distance, @by_distance;
    
    push @data, [ $lifespan, $distance , $bid, $ask ];
    
    splice(@by_lifespan, $i >= 0 ? $i : ~$i, 0, $#data);
    splice(@by_distance, $j >= 0 ? $j : ~$j, 0, $#data);
    
    潜艇:

    sub-bin首先搜索(&$\@){
    我的$compare=$\u0];
    #我的$value=$\u1];
    my$array=$\u2];
    我的$min=0;
    我的$max=$#$数组;
    如果$max==-1,则返回-1;
    my$ap=do{no strict'refs';\*{caller().::a'}};local*$ap;
    my$bp=do{no strict'refs';\*{caller().::b'}};local*$bp;
    *$ap=\($\[1]);
    而($min[$mid]);
    my$cmp=$compare->();
    如果($cmp<0){
    $max=$mid-1;
    }
    elsif($cmp>0){
    $min=$mid+1;
    }
    否则{
    如果$mid==$min,则返回$mid;
    $max=$mid;
    }
    }
    #将无符号整数转换为有符号整数。
    退回拆包('j',包装('j',~$min));
    }
    子对象向前运行(&$\@){
    我的$compare=$\u0];
    #我的$value=$\u1];
    我的$start=$\u2];
    my$array=$\u3];
    如果$start<0,则返回;
    my$ap=do{no strict'refs';\*{caller().::a'}};local*$ap;
    my$bp=do{no strict'refs';\*{caller().::b'}};local*$bp;
    *$ap=\($\[1]);
    我的$i=$start;
    而($i[$i]);
    my$cmp=$compare->()
    最后,;
    ++$i;
    }
    返回wantarray?($start..$i-1):$i-1;
    }
    

    您可能希望在浮点比较(即在
    $distance\u search\u cmp
    中)中使用公差。

    是否需要插入到列表中,是插入的结果还是其他元素?如果不是,排序数组+binsearch听起来不错。编写一个binsearch很容易,这样它就可以返回一个索引,如果找不到该元素,它将在该索引中找到该元素(如图所示)。这要求最多进行日志(N)比较(3000个元素约12次),而不是使用现有的方法进行N次比较(3000个元素)。在C中插入需要Mn小于n/2指针,所以仍然很快。还考虑使用数据库(例如SQLite)。它应该让你以最小的努力接近最大的效率。谢谢ikegami-我不知道如何对2D数组进行排序。至于我现在使用的键列表数组,它们足够短(即“我不确定如何对2D数组进行排序”。根据您的搜索。如果您可以在两点之间插入结果,则必须对点进行排序,对吗?查找依据是什么?///如果您遵循我发布的链接,它还显示了如何插入排序数组。它是O(N),因此它的伸缩性比append+re-sort(O(N log N))稍好一些,而且速度也快得多。///firstidx必须进行线性搜索
    sub binsearch_first(&$\@) {
       my  $compare = $_[0];
       #my $value   = $_[1];
       my  $array   = $_[2];
    
       my $min = 0;
       my $max = $#$array;
       return -1 if $max == -1;
    
       my $ap = do { no strict 'refs'; \*{caller().'::a'} };  local *$ap;
       my $bp = do { no strict 'refs'; \*{caller().'::b'} };  local *$bp;
    
       *$ap = \($_[1]);
       while ($min <= $max) {
          my $mid = int(($min+$max)/2);
          *$bp = \($array->[$mid]);
    
          my $cmp = $compare->();
          if ($cmp < 0) {
             $max = $mid - 1;
          }
          elsif ($cmp > 0) {
             $min = $mid + 1;
          }
          else {
             return $mid if $mid == $min;
             $max = $mid;
          }
       }
    
       # Converts unsigned int to signed int.
       return unpack('j', pack('J', ~$min));
    }
    
    sub get_run_forward(&$\@) {
       my  $compare = $_[0];
       #my $value   = $_[1];
       my  $start   = $_[2];
       my  $array   = $_[3];
    
       return if $start < 0;
    
       my $ap = do { no strict 'refs'; \*{caller().'::a'} };  local *$ap;
       my $bp = do { no strict 'refs'; \*{caller().'::b'} };  local *$bp;
    
       *$ap = \($_[1]);
    
       my $i = $start;
       while ($i <= $#$array) {
          *$bp = \($array->[$i]);
    
          my $cmp = $compare->()
             and last;
    
          ++$i;
       }
    
       return wantarray ? ($start..$i-1) : $i-1;
    }