3

我在matlab的树中使用递归调用,函数的基本结构在这里:

function recursion(tree, targetedFeatures)

    if (some conditions fulfilled)
      return;
    end

    for i = 1:1:size(targetedFeatures,2)
      .....
      .....
       if (some conditions that using index i is true)
          targetedFeatures(1,i) = 1; 
       end
    end

    if(tree has child nodes)
       recursion(tree.child(j).targetedFeatures)
    end
end

树的结构是这样的:

            root
           /  |  \
          /   |   \
         /    |    \
      leaf1  leaf2  leaf3

函数递归的输入参数是一个名为targetedFeatures的向量,假设它的初始值为[0 0 0],在访问leaf1的过程中,向量变为[1 0 0],但是在访问leaf2时,targetedFeature改回 [0 0 0]

我怀疑这是因为 matlab 中的向量不喜欢在其他编程语言中引用对象?

我怎样才能避免这个问题?谢谢。

4

3 回答 3

2

Matlab 对普通类型的变量使用按值调用,请参见此处。一种解决方法是让函数将修改后的副本作为输出参数返回:

function targetedFeatures = recursion(tree, targetedFeatures)
  ...
  targetedFeatures = recursion(tree.child(j).targetedFeatures);
  ...
end

evalin('caller', ...)相反,可以使用and模拟引用调用inputname

于 2013-10-28T19:19:38.070 回答
1

recursion函数需要修改时,会创建该函数调用的本地targetedFeatures副本。targetedFeatures如果您希望将更新传递回调用范围,则需要targetedFeatures从函数返回更新的内容。

function targetedFeatures = recursion(tree, targetedFeatures)

    if (some conditions fulfilled)
      return;
    end

    for i = 1:1:size(targetedFeatures,2)
      .....
      .....
       if (some conditions that using index i is true)
          targetedFeatures(1,i) = 1; 
       end
    end

    if(tree has child nodes)
       targetedFeatures = recursion(tree.child(j).targetedFeatures)
    end
end

这并不像在 C 中使用指针那样有效,但是您应该不会看到代码已经在执行的操作对性能造成重大影响,因为您在更新时已经在创建本地副本targetedFeatures

感谢 chappjc 提供了这篇文章的链接,该文章讨论了写时复制机制。

于 2013-10-28T19:22:09.960 回答
0

根据树的长度和最终深度,上面基于返回的解决方案很快就会变得非常难看,因为您总是必须更改根节点,而原则上您只想更改许多叶子中的一个。

相反,您可能希望研究实现 TreeNode 对象的句柄类。这将从以下简单的事情开始:

classdef TreeNode < handle

    properties
        targetedFeatures;
        child; % vector keeping handles to TreeNode children
        parent; % handle of the parent node, of which this node is a child
    end

    methods
        ...
    end
end

您显然必须填写添加/删除子节点等的方法。使用这样的树,您可以递归到最深的叶子并更改其值,而无需一直携带对顶级根节点的引用。一旦你有了这个,你应该能够在不修改的情况下使用你的函数。

一个有点类似的类的实现是链表的实现,在 MATLAB 文档中演示:http: //www.mathworks.de/de/help/matlab/matlab_oop/example--implementing-linked-lists.html 这里每个节点有一个前一个和下一个“孩子”,而不是一个父母和多个孩子,但总体结构非常相似。

如果您打算在这棵树上进行许多其他操作,例如添加/删除节点、搜索等,那么在某些时候肯定是值得的。如果您只是碰巧遇到了那棵树,并且一旦解决了这个问题就完成了,那么请选择基于回报的解决方案。

于 2013-10-29T07:47:38.310 回答