3

我在matlab中有一个这样的树结构:

node = 
  sub: [1x4 struct]

其中每个 sub 也是一个节点。

node.sub(1) = 
   sub: [1x4 struct]

等等,叶子节点有空子。假设我有一个节点并且我正在遍历树。有什么方法可以检查节点“对象”是否与树中的任何节点相同?我不是在谈论相同的价值。我希望“对象”是相同的。

例如:

mynode = tree.sub(1).sub(1);
isobjectequal(mynode, tree.sub(1).sub(1))
4

2 回答 2

2

从技术上讲,MATLAB 中的Astruct并不是您所说的“对象”。如果我创建一个结构,然后将其分配为另一个结构中的一个字段,那么两者现在是分离的。对第一个结构所做的任何更改都不会反映在我们刚刚制作的副本中。

a = struct('a', 2);
b = struct('b', a);

a.a = 3

% b.b.a == 2

您实际上只能可靠地检查两个s 的struct是否相等。

如果您确实想验证struct您要比较的两个 s 是否以相同的方式创建,您可以递归地struct检查并确定两个结构中每个元素的内存位置是否相同。这意味着结构是相等的,并且它们是使用相同的基础数据创建的。

对于一个非常简单的非深度嵌套结构,这可能看起来像这样。

function bool = isSameStruct(A, B)

    fmt = get(0, 'Format');

    format debug;
    memoryLocation = @(x)regexp(evalc('disp(x)'), '(?<=pr\s*=\s*)[a-z0-9]*', 'match');

    if isequaln(A, B)
        bool = true;
    elseif ~isequal(sort(fieldnames(A)), sort(fieldnames(B)))
        bool = false;
    else
        fields = fieldnames(A);

        bool = true;

        for k = 1:numel(fields)
            if ~isequal(memoryLocation(A.(fields{k})), memoryLocation(B.(fields{k})))
                bool = false;
                break;
            end
        end
    end

    format(fmt);
end

更新

另一种方法是为节点使用实际handle对象。一个基本的类看起来像这样。

classdef Node < handle
    properties
        Value
        Children
    end

    methods
        function self = Node(value)
            self.Value = value;
        end

        function addChild(self, node)
            self.Children = cat(2, self.Children, node)
        end
    end
end
于 2016-07-15T12:50:17.173 回答
1

如果您正在搜索“引用相等”,我想您应该使用句柄对象:

当您想要确定不同的句柄对象在所有对象属性中是否具有相同的数据时,请使用 isequal。当您想确定句柄变量是否引用同一个对象时,请使用 ==。

树测试.m

function treeTest()

root = TreeItem('Root');
child = TreeItem('Child');
grandChild = TreeItem('GrandChild');
grandGrandChild = TreeItem('GrandGrandChild');
grandGrandChild2 = TreeItem('GrandGrandChild');
root.Children{end+1} = child;
child.Children{end+1} = grandChild;
grandChild.Children{end+1} = grandGrandChild;
grandChild.Children{end+1} = grandGrandChild2;

findItem(root, grandGrandChild2)

    function findItem(tree, childToFind)
        if ~numel(tree.Children)
            return;
        end
        disp(['Traversing in ', tree.Name]);
        for i=1:numel(tree.Children)
            disp(['Iteration step: ', num2str(i)])
            if tree.Children{i} == childToFind
                disp(['Found! Name is ', tree.Children{i}.Name]);
                return;
            end
            findItem(tree.Children{i}, childToFind);

        end
    end
end

树项.m

classdef TreeItem < handle
    properties
        Name;
        Children;
    end

    methods
        function obj = TreeItem(name)
            obj.Name = name;
            obj.Children = {};
        end 
    end
end

输出是

Traversing in Root
Iteration step: 1
Traversing in Child
Iteration step: 1
Traversing in GrandChild
Iteration step: 1
Iteration step: 2
Found! Name is GrandGrandChild

正如您所看到的,两个grand-grand-child 对象在属性方面是相等的,但是Iteration step: 2输出中的条目证明,第一个grand-grand-child 被跳过了,因为该函数正在搜索第二个。

isequal和的区别==

>> grandGrandChild = TreeItem('GrandGrandChild');
grandGrandChild2 = TreeItem('GrandGrandChild');
>> isequal(grandGrandChild, grandGrandChild2)

ans =    1

>> grandGrandChild == grandGrandChild2

ans =   0
于 2016-07-15T13:07:12.730 回答