Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Matlab 位排序算法中存储管理的改进_Matlab_Sorting_Memory Management - Fatal编程技术网

Matlab 位排序算法中存储管理的改进

Matlab 位排序算法中存储管理的改进,matlab,sorting,memory-management,Matlab,Sorting,Memory Management,从《编程珍珠》一书中,我阅读了有关位排序算法的信息,下面是它在matlab中的简单示例 function result=bit_sort(A) % given array of integers, sort element of A using bit sort max_element=max(A); % find maximum element of A b=zeros(max_element,1); result=zeros(size(A)); n=length(A); for ii=1:

从《编程珍珠》一书中,我阅读了有关位排序算法的信息,下面是它在matlab中的简单示例

function result=bit_sort(A)
% given array of integers, sort  element of A using bit sort
max_element=max(A); % find maximum element of A
b=zeros(max_element,1);
result=zeros(size(A));
n=length(A);
for ii=1:n
    b(A(ii))=1;
end
k=1;
for ii=1:max_element
    if b(ii)==1
        result(k)=ii;
        k=k+1;
    end
end
end
这里还有一个很好的例子

A=[2 1 3 6 5 4 9 7];
>> result=bit_sort(A)

result =

     1     2     3     4     5     6     7     9
另一个例子

a=[2 1 4 100];
>> result=bit_sort(a)

result =

     1     2     4   100
代码运行良好,但我有一个不同的问题:在这行的代码声明中

max_element=max(A); % find maximum element of A
b=zeros(max_element,1);

占用内存的另一部分,在某些情况下可能不需要,例如,当我有4个元素:1 2 4 100时,如何有效地进行数组声明,以便实现两个条件:1。有效的内存管理2.保持算法的恒定速度?提前感谢

这是同一代码的矢量化版本

function result=bit_sort_vecorized(A)
% vectorized version
b(A(1:end))=1;
result=zeros(size(A));
n=length(b);
k=1;
for ii=1:n
    if b(ii)==1
        result(k)=ii;
        k=k+1;
    end
end
end


 A=[2 1 3 6 5 4 9 7];
>> result=bit_sort_vecorized(A)

result =

     1     2     3     4     5     6     7     9
1) 首先,您可以进一步使用矢量化: 替换此代码

k=1;
for ii=1:n
    if b(ii)==1
        result(k)=ii;
        k=k+1;
    end
end
关于这一点:

result = find( b == 1);
2) 关于计算速度: 我将这个循环用于
b=randi(10,1100000)
,得到这个循环:

result = find( b == 1);
使用循环
经过的时间为0.019176秒。

避免循环--
经过的时间为0.015142秒。


因此没有真正显著的优势

创建零和一的初始数组或定位
1
的位置不需要循环。相反,我们可以使用
ismember
find
生成结果

function result = bit_sort(x)    
    result = find(ismember(1:max(x), x));
end
解释

ismember
检查第一个输入中的每个条目是否存在于第二个输入中。在您的情况下,因为我们需要一个数组,其中每个数字的条目都在1和
max(x)
之间,如果值在
x
false
中,那么我们希望值为
true
,否则我们可以这样做

tmp = ismember(1:max(x), x)
%  1  1  1  1  1  1  1  0  1
然后我们可以使用
find
获取上述数组中每个1的位置

find(tmp)
%  1   2   3   4   5   6   7   9
其他一些备选方案

与使用
ismember
不同,您可以依赖这样一个事实:在MATLAB中,如果您使用索引分配给空数组,任何未指定的索引都将接收默认值
0
,因此我们可以使用

tmp(x) = true;          % Create a logical array
result = find(tmp);     % Again, use find to get the indices

此解决方案的好处是,您不必创建数组
1:max(x)
,因此可以节省内存。另外,
tmp
是一个
逻辑
数组,而不是一个
double
,因此它比您的示例中的
b
占用的空间少8倍。

为了完整性起见,下面是一个使用实际位向量的实现。位向量的大小为
ceil(max_element/8)
bytes,约为双数组大小的1/64或逻辑数组大小的1/8。它也可能比其他实现慢。它仍然是O(n),但常数无疑增加了

function result = bit_sort(A)
% given array of integers, sort  element of A using bit sort
% integers must be strictly positive
   max_element = max(A);   % find maximum element of A
   bitvec_size = ceil(max_element/8);   % 8 bits per uint8
   b = zeros(bitvec_size, 1, 'uint8');
   result = zeros(size(A));
   n = length(A);
   for ii=1:n
       current_num = A(ii) - 1;   % account for 1-based indexing
       byte_num = idivide(current_num, 8) + 1;   % find byte for our value
       % set bit # mod(n, 8) in byte found above
       %    add one again for 1-based bit indexing
       b(byte_num) = bitset(b(byte_num), mod(current_num, 8) + 1);
   end
   k = 1;
   for bytenum = 1:bitvec_size
      for bitnum = 1:8
         if bitget(b(bytenum), bitnum)
            result(k) = (bytenum-1)*8 + bitnum;   % bitnum = bitnum - 1 + 1
                                                  % I love 1-based indexing
            k = k + 1;
         end
      end
   end
end
对于输入数组中的每个值,使用整数除法将值除以8,从而将字节数(索引)查找到向量中。然后设置mod 8值在该字节中找到的位。在每个步骤中,都需要调整基于1的索引。有趣的是,您可以使用
ind2sub
来查找索引和位号,但这将更加神秘

您可以通过多种不同的方式实现相同的功能,使用
bit\u或
bit shift
,也可以使用
bi2de
进行解码。我不知道它们是否会更快,但这里的主要目标是展示一种减少位向量
b
内存使用的方法


如果知道最小数组值远大于1,则可以进行另一个较小的优化,即使用最小值作为数组的基础。只有当最小值约为最大值的一半(或更多)时,这才有意义,在这种情况下,您至少可以将位向量的大小减半。

如果A的元素数远小于最大值,则更有效的方法是使用稀疏矩阵:

find(sparse(A,1,A));
或更有效:

find(sparse(A,1,true));

只运行一次代码并不是一种很好的评测方式,尤其是对于JIT编译器。不管怎么说,你的计时显示相对速度提高了近25%。这可能真的很重要。感谢大家对存储的帮助?我的意思是,这种改变会提高存储利用率吗?@datodatuashvili,正如我在回答的最后一部分所说,如果你采用我的方法,它使用的
逻辑
数组比你正在使用的
数组小。上帝保佑你,明天我会详细介绍,它会排序数组吗?