低复杂度整数向量的有效表示

时间:2016-04-11 14:19:40

标签: matlab

V为整数向量,让 L V的长度。

现在,假设V不同值的 N 小于 L EM>

还可以假设V已排序,因此可以将其解释为 N 连续常量“块”的串联。

最后,可以假设,一旦初始化,V此后只读(又名不可变)。

(在我正在使用的情况下, L 介于10 6 和10 7 之间, N 约为20。)

将这种低复杂度数据存储在标准MATLAB L -long向量中是浪费的。 MATLAB是否有内置的 1 数据结构

  1. 与常规向量具有相同的接口(例如,可以使用表达式V(k)读取其 k -th元素,使用V(end)读取其最后一个元素,位置范围与V(p:q)等。)。
  2. 使用的存储空间远小于 L ×整数的大小。
  3. 顺便说一下,这里的问题让人联想到稀疏数组表示,但不完全相同(至少是AFAICT)。

    好的,这是我的解决方案,基于gariepy的回答:

    block_sizes = [5, 4, 3, 2];
    block_values = 1000 + (1:numel(block_sizes));
    interpolation_table = [0 cumsum(block_sizes)];
    V = @(i) interp1(interpolation_table, [NaN block_values], i, 'next');
    V(0)
    ans =
       NaN
    
    V(1:5)
    ans =
            1001        1001        1001        1001        1001
    
    V(6:9)
    ans =
            1002        1002        1002        1002
    
    V(10:12)
    ans =
            1003        1003        1003
    
    V(13:14)
    ans =
            1004        1004
    
    V(15)
    ans =
       NaN
    

    它有一个小疣,但是:

    V(end)
    ans =
            1001
    

    (如果在给出end作为参数时引发异常会更好,而不是给出一个完全疯狂的答案。)

    1 当然,我知道我总是可以尝试自己实现这样的事情,但如果我能避免它,我宁愿不重新发明轮子。功能

1 个答案:

答案 0 :(得分:1)

表示此数据的一种可能方法是插值表。

假设vec是你的长度L向量。首先,计算出现次数:

[num_occurrences, y_values] = hist(vec, unique(vec));

然后,构建插值表示:

interp_table = zeros(1,length(y_values) + 1);
interp_table(1) = 1;
y_values(end+1) = y_values(end) + 1;  % Need to create a "fake" value at the end of the interpolation table
for i = 2:length(y_values)
    interp_table(i) = interp_table(i-1) + num_occurrences(i-1);
end

最后,定义一个函数句柄,为你提供"类似数组"访问你想要的。

my_fun = @(x) interp1(interp_table, y_values, x, 'previous');

示例:

>> vec = [1 1 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 ];
>> my_fun(1)
ans =
     1
>> my_fun(2)
ans =
     1
>> my_fun(3)
ans =
     2
>> my_fun(6)
ans =
     2
>> my_fun(7)
ans =
     2
>> my_fun(8)
ans =
     3
>> my_fun(17)
ans =
     3
>> my_fun(18)  %% This is vec(L+1), so it should never be needed
ans =
     4
>> my_fun(19)  %% Above index L+1, values are not defined
ans =
   NaN

示例演示了一个小警告:不应使用my_fun(L)以上的值,其中L是由插值表表示的原始矢量的长度。所以这给你类似数组的访问,虽然你不能直接计算"长度"这个插值表。

编辑:请注意,您可以使用此插值功能执行范围:

>> my_fun(1:17)
ans =
  Columns 1 through 15
     1     1     2     2     2     2     2     3     3     3     3     3     3     3     3
  Columns 16 through 17
     3     3