Arrays 什么';用MATLAB删除数组中最后一个元素的时间复杂度?
我不知道MATLAB中数组的数据结构。它使用FiFo吗 我尝试从列和行向量中删除最后一个元素。时间复杂度取决于大小Arrays 什么';用MATLAB删除数组中最后一个元素的时间复杂度?,arrays,matlab,data-structures,Arrays,Matlab,Data Structures,我不知道MATLAB中数组的数据结构。它使用FiFo吗 我尝试从列和行向量中删除最后一个元素。时间复杂度取决于大小N 如何删除O(1)中的最后一个元素 基本上pop() A = ones(1,50); B = ones(1,10); tic A(1) = []; toc tic A(49) = []; toc tic B(1) = []; toc tic B(9) = []; toc Elapsed time is 0.000195 seconds. Elapsed time is 0.00
N
如何删除O(1)
中的最后一个元素
基本上
pop()
A = ones(1,50);
B = ones(1,10);
tic
A(1) = [];
toc
tic
A(49) = [];
toc
tic
B(1) = [];
toc
tic
B(9) = [];
toc
Elapsed time is 0.000195 seconds.
Elapsed time is 0.000085 seconds.
Elapsed time is 0.000061 seconds.
Elapsed time is 0.000051 seconds.
您可以看到,删除数组的最后一个元素要比删除第一个元素快。根据数组长度,使用tic toc
,来测量时间
A = ones(1,50);
B = ones(1,10);
tic
A(1) = [];
toc
tic
A(49) = [];
toc
tic
B(1) = [];
toc
tic
B(9) = [];
toc
Elapsed time is 0.000195 seconds.
Elapsed time is 0.000085 seconds.
Elapsed time is 0.000061 seconds.
Elapsed time is 0.000051 seconds.
您可以看到,删除数组的最后一个元素要比删除第一个元素快。经过快速测试,我发现就地重新分配要比删除元素快得多。但这两种操作的性能仍然取决于向量大小。。。我只是认为这不可能如您所愿在O(1)
中实现,因为Matlab内部处理内存的方式
第一种方法:
A = rand(100,1);
tic();
A(end) = [];
toc(); % Average elapsed time: 0.000015 seconds
B = rand(10000,1);
tic();
B(end) = [];
toc(); % Average elapsed time: 0.000061 seconds
A = rand(100,1);
tic();
A = A(1:end-1);
toc(); % Average elapsed time: 0.000007 seconds
B = rand(10000,1);
tic();
B = B(1:end-1);
toc(); % Average elapsed time: 0.000017 seconds
第二种方法:
A = rand(100,1);
tic();
A(end) = [];
toc(); % Average elapsed time: 0.000015 seconds
B = rand(10000,1);
tic();
B(end) = [];
toc(); % Average elapsed time: 0.000061 seconds
A = rand(100,1);
tic();
A = A(1:end-1);
toc(); % Average elapsed time: 0.000007 seconds
B = rand(10000,1);
tic();
B = B(1:end-1);
toc(); % Average elapsed time: 0.000017 seconds
我对Matlab的了解不够深入,无法准确解释引擎盖下发生了什么,以及为什么这两种方法之间存在如此大的差异。但我可以猜一猜
在第一种方法中,Matlab必须:
- 将
end
计算为实向量偏移量李>
- 找出需要移除的元素数量李>
- 分配一个新的大小数组
total_elements-removed_elements
李>
- 取数组中未触及的部分,缓冲区将其复制到新数组中李>
- 用新的数组引用替换以前的数组引用李>
- 取消分配上一个数组
在第二种情况下,Matlab必须:
- 将
end
计算为实向量偏移量李>
- 分配一个大小
索引元素的新数组
李>
- 获取所需的数组范围并将其复制到新数组中李>
- 用新的数组引用替换以前的数组引用李>
- 取消分配上一个数组
然而,我们离O(1)
还有很长的路要走。经过快速测试,我发现就地重新分配要比元素删除快得多。但这两种操作的性能仍然取决于向量大小。。。我只是认为这不可能如您所愿在O(1)
中实现,因为Matlab内部处理内存的方式
第一种方法:
A = rand(100,1);
tic();
A(end) = [];
toc(); % Average elapsed time: 0.000015 seconds
B = rand(10000,1);
tic();
B(end) = [];
toc(); % Average elapsed time: 0.000061 seconds
A = rand(100,1);
tic();
A = A(1:end-1);
toc(); % Average elapsed time: 0.000007 seconds
B = rand(10000,1);
tic();
B = B(1:end-1);
toc(); % Average elapsed time: 0.000017 seconds
第二种方法:
A = rand(100,1);
tic();
A(end) = [];
toc(); % Average elapsed time: 0.000015 seconds
B = rand(10000,1);
tic();
B(end) = [];
toc(); % Average elapsed time: 0.000061 seconds
A = rand(100,1);
tic();
A = A(1:end-1);
toc(); % Average elapsed time: 0.000007 seconds
B = rand(10000,1);
tic();
B = B(1:end-1);
toc(); % Average elapsed time: 0.000017 seconds
我对Matlab的了解不够深入,无法准确解释引擎盖下发生了什么,以及为什么这两种方法之间存在如此大的差异。但我可以猜一猜
在第一种方法中,Matlab必须:
- 将
计算为实向量偏移量李>end
- 找出需要移除的元素数量李>
- 分配一个新的大小数组
李>total_elements-removed_elements
- 取数组中未触及的部分,缓冲区将其复制到新数组中李>
- 用新的数组引用替换以前的数组引用李>
- 取消分配上一个数组
- 将
计算为实向量偏移量李>end
- 分配一个大小
李>索引元素的新数组
- 获取所需的数组范围并将其复制到新数组中李>
- 用新的数组引用替换以前的数组引用李>
- 取消分配上一个数组
然而,我们远远没有遵循来自的计时脚本,它处理相反的问题——增长一个向量,我尝试了两种方法来删除最后一个元素:
building_array = building_array(1:end-1);
building_array(end) = [];
如图所示,前者(蓝色)比后者(红色)快:
关于这两种形式的计时方式不同的原因,我的猜测是,MATLAB的JIT(实时编译器)针对一种语法比另一种更优化。没有技术上的理由说明一个比另一个快
我真的很惊讶,成本在元素数量上是线性的,这与当时添加元素的行为非常不同
测试代码(修改自):
按照中处理相反问题的计时脚本——增长向量,我尝试了两种方法来删除最后一个元素:
building_array = building_array(1:end-1);
building_array(end) = [];
如图所示,前者(蓝色)比后者(红色)快:
关于这两种形式的计时方式不同的原因,我的猜测是,MATLAB的JIT(实时编译器)针对一种语法比另一种更优化。没有技术上的理由说明一个比另一个快
我真的很惊讶,成本在元素数量上是线性的,这与当时添加元素的行为非常不同
测试代码(修改自):
免责声明:这不是一个真正的建议,它只是一个愚蠢的方式来实际获取O(1)运行时 对,在给出免责声明后,实际上可以在“Matlab”中生成O(1)pop命令。解决方案不是用Matlab,而是用Python。困惑 基本上,使用
py.list()
将向量转换为Python列表,然后可以执行O(1)pop
命令。因此,您可以执行以下操作:
a = randn(1,1e4);
li=py.list(a);
b = li.pop;
然而,正如您可能已经猜到的,通过Matlab进行类型转换和运行python并不是我所说的快速。所以,即使我们可以保持一个恒定的运行时,这个常数对于它来说太大了,没有任何用处
在图中,蓝色是Matlab/Python解决方案,而红色(-ish)是最佳解决方案,如Tommaso和Cris所示
很明显,我们保持了O(1)的样子,但这是有代价的
参考代码:
num_averages = 100;
num_sims = 10000;
time_store = nan(num_sims, num_averages);
for i = 1:num_averages
building_array = rand(1,num_sims);
li = py.list(building_array);
for j = 1:num_sims
tic;
li.pop;
time_store(j, i) = toc;
end
end
编辑:此方法比纯Matlab解决方案快的大小实际上在某个合理的限制范围内~150000
注:f