使用treeplot将嵌套单元格绘制为树:MATLAB

Zan*_*der 3 tree matlab cells multidimensional-array

我有一个表示树结构的复杂单元格:

CellArray = {1,1,1,{1,1,1,{1,1,{1,{1 1 1 1 1 1 1 1}, 1,1}, 1,1},1,1,1},1,1,1,{1,1,1,1}};
Run Code Online (Sandbox Code Playgroud)

我想通过使用来绘制代表树treeplot(p),但我不确定如何构造数组p以使其正确显示.

Wol*_*fie 7

我们可以创建一个递归函数,它可以探索你的单元格数组,并为每个节点的父节点创建一个树指针数组(如文档中所述).

此函数采用包含标量或嵌套单元格数组的单元格数组(如您的问题中的那个).


treebuilder 逻辑:

  1. 如果项是标量,请为其指定父节点编号,将节点编号增加1
  2. 如果项是单元格数组,则treebuilder在该单元格上运行,返回已达到的最大节点数(以及生成的子树).
  3. 由于步骤2的递归函数,所以重复直到每个元素完成

功能:

function treearray = getTreeArray(cellarray)
    % initialise the array construction from node 0
    treearray = [0, treebuilder(cellarray, 1)]; 
    % recursive tree building function, pass it a cell array and root node
    function [out, node] = treebuilder(cellarray, rnode)
        % Set up variables to be populated whilst looping
        out = []; 
        % Start node off at root node
        node = rnode;
        % Loop over cell array elements, either recurse or add node
        for ii = 1:numel(cellarray)
            tb = []; node = node + 1;
            if iscell(cellarray{ii})
                [tb, node] = treebuilder(cellarray{ii}, node);
            end
            out = [out, rnode, tb];   
        end
    end
end
Run Code Online (Sandbox Code Playgroud)

使用简单的例子

这是一个比你更简单的例子,所以我们可以很容易地检查逻辑.

myCellArray = {1 1 {1 1 1 {1 1 1}}};
% This cell array has 3 levels: 
% - 3 child nodes (2,3,4) of the root node (1) 
% - Last node on the first level (4) has 4 children:
%     - 4 child nodes on second level (5,6,7,8) 
%     - Last node on the first level (8) has 3 children:
%         - 3 child nodes on third level (9,10,11)
myTreeArray = getTreeArray(myCellArray);
% Output, we see the corresponding nodes as listed above:
% [0 1 1 1 4 4 4 4 8 8 8]
treeplot(myTreeArray)
Run Code Online (Sandbox Code Playgroud)

简单


你的单元阵列

我认为这可以按预期工作,请注意您不必定义myCellArraymyTreeArray变量:

treeplot(getTreeArray({1,1,1,{1,1,1,{1,1,{1,{1 1 1 1 1 1 1 1}, 1,1}, 1,1},1,1,1},1,1,1,{1,1,1,1}}))
Run Code Online (Sandbox Code Playgroud)

这是输出图像,表明该算法可以处理更复杂的树.速度似乎也不是太糟糕,尽管显示极其复杂的树木无论如何都会相当多余!


编辑:标记节点

您可以通过获取其位置来标记节点,treelayout并在构建树阵列时遇到它们时跟踪这些值.该功能应该调整为这样的"保持跟踪",如下所示:

function [treearray, nodevals] = getTreeArray(cellarray)
    % initialise the array construction from node 0
    [nodes, ~, nodevals] = treebuilder(cellarray, 1); 
    treearray = [0, nodes];
    % recursive tree building function, pass it a cell array and root node
    function [out, node, nodevals] = treebuilder(cellarray, rnode)
        % Set up variables to be populated whilst looping
        out = []; nodevals = {};
        % Start node off at root node
        node = rnode;
        % Loop over cell array elements, either recurse or add node
        for ii = 1:numel(cellarray)
            node = node + 1;
            if iscell(cellarray{ii})
                [tb, node, nv] = treebuilder(cellarray{ii}, node);
                out = [out, rnode, tb];  
                nodevals = [nodevals, nv];
            else
                out = [out, rnode];
                nodevals = [nodevals, {node; cellarray{ii}}];
            end 
        end
    end
end
Run Code Online (Sandbox Code Playgroud)

注意:如果要为绘图上的每个节点编号,可以使用类似的调整来跟踪节点编号而不是节点.

我在这里使用了一个单元格数组,以便您可以在每个节点上使用文本或数值.如果您只想要数值,则可能会缩短后格式以存储nodevals在矩阵中.

然后绘制这个你可以使用

% Run the tree building script above
[treearray, nodevals] = getTreeArray(myCellArray);
% Plot
treeplot(treearray);
% Get the position of each node on the plot  
[x,y] = treelayout(treearray);
% Get the indices of the nodes which have values stored
nodeidx = cell2mat(nodevals(1,:));
% Get the labels (values) corresponding to those nodes. Must be strings in cell array
labels = cellfun(@num2str, nodevals(2,:), 'uniformoutput', 0);
% Add labels, with a vertical offset to the y coords so that labels don't sit on nodes
text(x(nodeidx), y(nodeidx) - 0.03, labels);
Run Code Online (Sandbox Code Playgroud)

单元格的示例输出myCellArray = {{17, 99.9}, 50},我选择这些数字以表明它们不是实际的"节点数"!

在此输入图像描述