Algorithm 在MATLAB上堆排序应该非常慢吗?

Algorithm 在MATLAB上堆排序应该非常慢吗?,algorithm,matlab,sorting,heapsort,clrs,Algorithm,Matlab,Sorting,Heapsort,Clrs,我在MATLAB中编写了一个堆排序函数,它工作得很好,只是当输入长度大于或等于1000时,可能需要很长时间(例如,1000的长度需要半秒)。我不确定是MATLAB在堆排序算法上运行得不是很快,还是我的代码需要改进。 我的代码如下所示: function b = heapsort(a) [~,n] = size(a); b = zeros(1,n); for i = 1:n a = build_max_heap(a); b(n+1-i) = a(1); temp = a

我在MATLAB中编写了一个堆排序函数,它工作得很好,只是当输入长度大于或等于1000时,可能需要很长时间(例如,1000的长度需要半秒)。我不确定是MATLAB在堆排序算法上运行得不是很快,还是我的代码需要改进。 我的代码如下所示:

function b = heapsort(a)

[~,n] = size(a);
b = zeros(1,n);
for i = 1:n
    a = build_max_heap(a);
    b(n+1-i) = a(1);

    temp = a(1);
    a(1) = a(n+1-i);
    a(n+1-i) = temp;

    a(n+1-i) = [];
    a = heapify(a,1);
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function a = build_max_heap(a)
[~,n] = size(a);
m = floor(n/2);
for i = m:-1:1
    a = heapify(a,i);
end
end
function a = heapify(a,i)
[~,n] = size(a);

left = 2*i;
right = 2*i + 1;

if left <= n 
    if a(left) >= a(i)
        large = left;
    else
        large = i;
    end
else
    return
end
if right <= n
    if a(right) >= a(large)
        large = right;
    end
end

if large ~= i
    temp = a(large);
    a(large) = a(i);
    a(i) = temp;
    a = heapify(a,large);
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function a = build_max_heap(a)
[~,n] = size(a);
m = floor(n/2);
for i = m:-1:1
    a = heapify(a,i);
end
end
function a = heapify(a,i)
[~,n] = size(a);

left = 2*i;
right = 2*i + 1;

if left <= n 
    if a(left) >= a(i)
        large = left;
    else
        large = i;
    end
else
    return
end
if right <= n
    if a(right) >= a(large)
        large = right;
    end
end

if large ~= i
    temp = a(large);
    a(large) = a(i);
    a(i) = temp;
    a = heapify(a,large);
end
end
函数a=heapify(a,i)
[~,n]=尺寸(a);
左=2*i;
右=2*i+1;
如果左=a(i)
大=左;
其他的
大=i;
结束
其他的
返回
结束
如果右=a(大)
大=右;
结束
结束
如果大~=i
温度=a(大);
a(大)=a(i);
a(i)=温度;
a=heapify(a,大);
结束
结束
我知道可能是代码
a(n+1-I)=[]这可能会占用很多时间。但是,当我将
[]
更改为
-999
(低于输入向量的任何数字)时,这没有帮助,反而花费了更多的时间。

您应该使用检查哪些行花费的时间最多。它肯定是
a(n+1-i)=[]这会减慢您的功能

在循环中调整数组的大小非常慢,所以您应该始终避免这样做

一个简单的测试:

  • 创建一个以大向量为输入的函数,并迭代删除元素,直到其为空
  • 创建一个函数,以相同的向量作为输入,并迭代地将每个值设置为
    0
    Inf
    NaN
    或其他值
用于检查哪个功能更快。您将看到最后一个函数大约快100倍(当然取决于向量的大小)

-999
花费更多时间的原因很可能是因为
a
不再变得越来越小,因此
a=heapify(a,1)不会越来越快。我还没有测试过它,但是如果您在第一个函数中尝试以下操作,您可能会得到一个更快的程序(您必须在代码中的其他位置插入
n+1-I)
,但我将把这留给您):

请注意,我将
I
更改为
ii
。这部分是因为我想给你一个好的建议,部分是为了避免被提醒。

你应该使用检查哪些行花费的时间最多。它肯定是
a(n+1-i)=[]这会减慢您的功能

在循环中调整数组的大小非常慢,所以您应该始终避免这样做

一个简单的测试:

  • 创建一个以大向量为输入的函数,并迭代删除元素,直到其为空
  • 创建一个函数,以相同的向量作为输入,并迭代地将每个值设置为
    0
    Inf
    NaN
    或其他值
用于检查哪个功能更快。您将看到最后一个函数大约快100倍(当然取决于向量的大小)

-999
花费更多时间的原因很可能是因为
a
不再变得越来越小,因此
a=heapify(a,1)不会越来越快。我还没有测试过它,但是如果您在第一个函数中尝试以下操作,您可能会得到一个更快的程序(您必须在代码中的其他位置插入
n+1-I)
,但我将把这留给您):


请注意,我将
I
更改为
ii
。这部分是因为我想给您一个好建议,部分是为了避免被提醒。

尝试使用?我不完全确定,但似乎您假设值是通过引用传递的。不幸的是,Matlab并非如此:(.Matlab使用写时复制,这意味着当您修改输入时它将进行复制。您可以通过使用排序向量和随机向量来确认这一点。如果结果比更糟的情况大O更糟,这可能就是问题所在。尝试不同大小的向量。除此之外,Matlab中的排序函数据说速度很快。我不能用引用来支持这一点,但我的一位Matlab专家朋友告诉我不要在大循环中调用函数,而是“post”函数本身直接在循环中,这是由于在循环中重复调用函数时会产生一些开销。因此,一个测试可能包括
build\u max\u heap
heapify
(仅用于测试此假设)。可能不再是一个问题,这取决于您使用的是哪个Matlab版本。@dfri我使用的是Matlab R2015b和我编写的其他排序函数,这很好。因此,情况可能不是这样。@PaulR Profiler准确地解决了我的问题。
[~,n]=size(a);
n=length(a)花费的时间多得多
如果没有您的帮助,我永远不会想到这一点。非常感谢。尝试使用?我不完全确定,但似乎您假设值是通过引用传递的。不幸的是,Matlab的情况并非如此:(.Matlab使用写时复制,这意味着当您修改输入时它将进行复制。您可以通过使用排序向量和随机向量来确认这一点。如果结果比更糟的情况大O更糟,这可能就是问题所在。尝试不同大小的向量。除此之外,Matlab中的排序函数据说速度很快。我不能用引用来支持这一点,但我的一位Matlab专家朋友告诉我不要在大循环中调用函数,而是“post”函数本身直接在循环中,这是由于在循环中重复调用函数时会产生一些开销。因此,一个测试可能包括
build\u max\u heap
heapify
(仅用于测试此假设)。可能不再是一个问题,这取决于您使用的是哪个Matlab版本。@dfri我使用的是Matlab R2015b和其他排序函数