在这种特殊情况下如何避免嵌套for循环?

时间:2018-03-07 04:37:32

标签: matlab performance nested-loops

我编写了一个BFS(广度优先搜索)路径规划算法。它与小网格(例如15乘15)完美配合,但是当涉及更大的网格(例如150乘250)时,这是一个灾难。使用 tic toc 命令,我发现它花费的时间最多(效率最低的位),问题在于嵌套的for循环。我知道使用嵌套for循环被认为是坏的,我需要帮助用其他东西替换它(如果可能的话,避免使用循环)。

for j=1:length(F)
    for k = 1:length(Closed)
        if(F(j) == Closed(k))
            F(j) = 0;
        end
    end
end

Closed = [Closed current];

代码的这一部分的目的是替换作为父节点的 F 的元素(我们来自哪里)。这样就可以忽略任何重复。

  • F 是1个 n 向量,用于存储可以从当前节点传播的邻居节点。

注意:我使用8连接空间,因此 n 总是小于8.

  • 已关闭作为空向量启动,用于存储已访问节点列表(通过水平连接)。

  • 当前是1到37901之间的数字,代表当前节点。

我知道有关于嵌套循环的另一个question,但我的问题是不同的。谢谢你的帮助!

1 个答案:

答案 0 :(得分:0)

这段代码很慢的原因并不是你有嵌套循环,而是你实现了O(n 2 )算法。

您应该使用逻辑数组来指示“已关闭”的节点。这将使查找更有效。

考虑您有N = 37901个节点。因此,初始化Closed数组:

Closed = false(1,N);

现在要检查节点F(j)是否已关闭,您只需执行Closed(F(j)),如果已关闭则为true

现在您的循环可以替换为

F(Closed(F)) = [];
Closed(current) = true;

因为Closed(F)是一个与F大小相同的数组,对于封闭节点是正确的。您可以使用此数组索引到F,并删除所有已关闭的节点。我正在删除这些节点,而不是为它们分配0,这样F总是可以用来索引Closed。如果我们在那里写0,它就不再是逻辑数组。如果您不需要更改F的形状,则必须在编制索引之前进行一些额外的测试。

请注意,Closed = [Closed current]也比Closed(current) = true慢很多,因为它创建了一个新的数组,旧的Closed数组被复制到其中。

请注意,你可以删除代码中的嵌套循环,如下所示,但它不一定会更快,因为算法仍然是O(n 2 )(你要比较每个F中每个元素的Closed中的元素。

for j=1:length(F)
   if any(F(j) == Closed)
      F(j) = 0;
   end
end